Search code examples
javascriptreactjstinymce

tinymce create comment function does not read updated state


I have implemented an editor with tinymce package and I have the comments plug in. In addition I have built a functionality as follows: When a user select a text, I store it on a state variable in order to read it from the tiny's built in create function and send all the data to my backend. Overall I want when a user select a text in order to create a comment, to send the highlighted text to my backend through the tiny's create function but the create function only reads the initial state of the variable and does not read the updated value. The code id as below:

import { Editor as EditorMce } from "@tinymce/tinymce-react";
//... some imports

function Editor() {
let [highlightedText, setHighlightedText] = useState("");

  const tinycomments_create = (req, done, fail) => {
    const { content, createdAt } = req;

    console.log("highligt inside create function");
    console.log(highlightedText); //This is always an empy string, the initial value
//and does not update when user highlights a text

    fetch("my-backend-endpoint", {
      method: "POST",
      body: JSON.stringify({
        content,
        createdAt,
        highlightedText,
      }),
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
    })
      .then((response) => {
        if (!response.ok) {
          throw new Error("Failed to create comment");
        }
        return response.json();
      })
      .then((req2) => {
        const conversationUid = req2.id;
        done({ conversationUid });
      })
      .catch((e) => {
        fail(e);
      });
  };

//... some existing code and I return the component

<EditorMce
                value={session ? session.sessionText : ""}
                onEditorChange={handleOnEditorChange}
                init={{
                  init_instance_callback: (editor) => {
                    editor.on("MouseUp", function (e) {
                      if (e.view.getSelection().toString() !== "") {
                        setHighlightedText(e.view.getSelection().toString());
                      }
                    });
                  },
                  content_css: "writer",
                  height: "80%",
                  width: "95%",
                  plugins: [
                    "tinycomments",
                    "advlist",
                    "autolink",
                    "lists",
                    "link",
                    "image",
                    "charmap",
                    "preview",
                    "anchor",
                    "searchreplace",
                    "visualblocks",
                    "code",
                    "fullscreen",
                    "insertdatetime",
                    "media",
                    "table",
                    "code",
                    "help",
                    "wordcount",
                  ],
                  menubar: "file edit view insert format tools tc",
                  menu: {
                    tc: {
                      title: "Comments",
                      items: "addcomment showcomments deleteallconversations",
                    },
                  },
                  toolbar:
                    "undo redo | fontsizeinput fontfamily | blocks | " +
                    "bold italic forecolor backcolor | alignleft aligncenter " +
                    "alignright alignjustify | bullist numlist outdent indent | " +
                    "removeformat | addcomment showcomments | help",
                  content_style:
                    "body { font-family:Helvetica,Arial,sans-serif; font-size:16px }" +
                    ".tox-comments-visible span.tox-comment  { background-color: #90EE90!important; }.tox-comments-visible span.tox-comment--active { background-color: black; }",
                  tinycomments_create,
                  tinycomments_reply,
                  tinycomments_edit_comment,
                  tinycomments_delete,
                  tinycomments_delete_all,
                  tinycomments_delete_comment,
                  tinycomments_lookup,
                }}
              />
}

How can I update the value of highlightedText inside tinycomments_create. I have tried the useCallback hook with no result. Also I have tried to add the tinycomments_create inside a useEffect and set it every time the highlightedText updates but again with no results. Any thoughts on that?


Solution

  • Instead of using useState, you can use a useRef:

    // replace
    const [highlightedText, setHighlightedText] = useState("");
    
    // by
    const highlightedText = useRef("");
    

    Then when updating this value

    // replace
     setHighlightedText(e.view.getSelection().toString());
    
    // by
    highlightedText.current = e.view.getSelection().toString();
    

    Finally, inside the tinycomments_create function, you can read the most up-to-date value from highlightedText.current.

    Note that updating a ref won't cause a render, thus the UI won't get updated. If you want the UI to update, you would have to use a useState along with the proposed useRef approach.

    TLDR: using useRef is essential for the tinycomments_create to read the last value of highlightedText; while using useState is essential if you want to make a render and update the UI.