Search code examples
reactjstinymce

How to divide tinymce text in React into sections and change only these sections onEditorChange to send them on backend?


I have a React app which has a TinyMCE instance and upon changing specific sections on editor I want to save them on the backend, only the ones that have been changed. Is it possible to achieve something like that? In vanillajs and html you would have different divs with ids and you could be able to get a reference on them and change the corresponding part. But in React it is not the same.

What I have tried is to render the text coming from the backend into the editor by using a state variable that has these sections as a dictionary but now I want upon changing only one section to change the corresponding value. what I want to derive is the section name to update the server ( and the corresponding key value pair in the state var). In the example I provided the html content of each section is small but in a real app it can be big. The model is a dictionary which has as keys the section names and as value an object with an id and the html value like this:

{ 
  header: { section_id: 2, value: "<h1> This is the header </h1>"},
  body: { section_id: 1, value: "<p>Body content</p>" }
  
  ...
}

function MyComponent() {
  // here is the state var that I am taking from the backend
 // and want to update it according to user changes 
  const [value, setValue] = useState({
    header: { section_id: 2, value: "<h1>This is the header</h1>" },
    body: { section_id: 1, value: "<p>Body</p>" }
  });

  const editorValue = Object.values(value)
    .map((v) => v.value)
    .join("<br/>");

  return (
    <Editor
      value={editorValue}
       onEditorChange={(newValue, editor) => {
       // here I would like to get the section part which I am updating somehow
       setValue(newValue);
     }}
    />
  );
}

Is there any way to get the section reference somehow according to my attempt or another approach I could follow to achieve the same goal?

Demo


Solution

  • So what I did in the end is the following:

    I used the dictionary to loop over the values I have and create as many editors as the values I have inside the dictionary. With this way, I can pass the key which is the section I am changing dynamically and I know which section I am updating so I can send the changed text on the backend to save it separately.

    const [editorValue, setEditorValue] = useState({
        header: { section_id: 2, value: "<h1>This is the header</h1>" },
        body: { section_id: 1, value: "<p>This is the body</p>" }
      });
    
    const handleEditorChange = (value, editor, key) => {
        setEditorValue((prevState) => ({
          ...prevState,
          [key]: { ...prevState[key], value }
        }));
      };
    
      return Object.entries(editorValue).map(([key, value]) => (
        <Editor
          inline
          menubar={false}
          value={value.value}
          onEditorChange={(value, editor) => handleEditorChange(value, editor, key)}
        />
      ));
    

    I have updated also the demo to include my solution in case someone has the same issue in the future.