Home > Back-end >  React - save components visualization to JSON and read it back
React - save components visualization to JSON and read it back

Time:01-29

Imagine I have a hierarchy of react components, e.g. meals of the day

|------- breakfast --------|
|  Meal1_image.png banana  |
|  Meal2_image.png porridge|


|------- lunch-------------|
|  Meal3_image.png toast   |
|  Meal4_image.png apple   |

I can add meals to a meal group (e.g. to the lunch group), I can add more lunch groups (e.g. midday snack) and so on.. it's a variable list of components and I give the user the ability to add meals and meal groups with ' ' buttons, or to delete them and so on.

How would I go to save these in a text json and to read them back? I read about "serializing react components" but maybe I don't need all of that stuff, I would just need to save a json like

{
   "breakfast": {
      {"food": "banana", "image": "Meal1_image.png"},
      {"food": "porridge", "image": "Meal2_image.png"},
   },
   "lunch" : ... and so on ...
}

is there any simple way to achieve this or should I just go with components serialization with things like https://github.com/zasource-dev/React-Serialize ?

CodePudding user response:

If you mean physical saving in a file, then you need to have node js to access the file system of your phone or PC, your server:

   // file system module to perform file operations
    const fs = require('fs');
     
    // json data
    var jsonData = '{"persons":[{"name":"John","city":"New York"},{"name":"Phil","city":"Ohio"}]}';
     
    // parse json
    var jsonObj = JSON.parse(jsonData);
    console.log(jsonObj);
     
    // stringify JSON Object
    var jsonContent = JSON.stringify(jsonObj);
    console.log(jsonContent);
     
    fs.writeFile("output.json", jsonContent, 'utf8', function (err) {
        if (err) {
            console.log("An error occured while writing JSON Object to File.");
            return console.log(err);
        }
        console.log("JSON file has been saved.");
    });

If we are talking about transformation for axios request, then you need to use the following javascript methods JSON.stringify() for json transformation and JSON.parse() for reading to transformation in javascript.

If you just want to transform the object in the hook state, this is also fine.

CodePudding user response:

Question is basically too wide, but anyway, just split your task by subtasks.

  1. Design the data models you are going to work with. Create a prototype of it, try to render it as is. Regarding your prototype - that is not valid js object, so i changed it a bit in my example. Note - for .map methods you need to use unique keys.

  2. Figure out what will be the best place to keep your data (in state). You can store it in some component, you can store it in context and add all the needed methods to it and pass them down to your components. I did everything in a component for simplicity of example.

  3. Add download/upload/parsing functions and wire everything up.

If I got your question right - you want each Client to be able to download and upload the Data to a local JSON file on Client, so no server interaction.

const { useState } = React;

function download(content, mimeType, filename) {
  const a = document.createElement("a");
  const blob = new Blob([content], { type: mimeType });
  const url = URL.createObjectURL(blob);
  a.setAttribute("href", url);
  a.setAttribute("download", filename);
  a.click();
}

function upload(event, callback) {
  const input = event.target;

  const reader = new FileReader();
  reader.onload = function () {
    const text = reader.result;
    callback(text);
  };
  reader.readAsText(input.files[0]);
}

const DEFAULT_DATA = {
  breakfast: [
    { food: "banana", image: "Meal1_image.png" },
    { food: "porridge", image: "Meal2_image.png" }
  ],
  lunch: [{ food: "banana", image: "Meal1_image.png" }]
};

function App() {
  const [data, setData] = useState(DEFAULT_DATA);

  const onDownloadClick = (e) => {
    download(JSON.stringify(data), "application/json", "file1.json");
  };

  const onUpload = (e) => {
    upload(e, (text) => setData(JSON.parse(text)));
  };

  return (
    <div className="App">
      {Object.entries(data).map(([section, items]) => (
        <div key={section}>
          <p>{section}</p>
          <ul>
            {items.map((item) => (
              <li key={item.food}>
                <p>{item.food}</p>
              </li>
            ))}
          </ul>
        </div>
      ))}

      <button onClick={onDownloadClick} type="button">
        Download JSON
      </button>
      <input type="file" accept="application/json" onChange={onUpload} />
    </div>
  );
}



// v18.x 
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<div id="root"></div>

How to test - Download JSON file, open it and change something in it, like "banana" to "banana111", save, upload the file back and observe the updated values.

Not sure what is the plan about Images, but in worst case - you can store images in JSON as base64 strings.

  • Related