Is there a way to make an async request inside a lexical editor update in react?

816 Views Asked by At

I am using Lexical as a rich text editor package in React. It has a method for selecting highlighted text and updating it. This works fine when I use some predefined string to update it but I would like to send the highlighted text to an API then use the response to update the text on the screen and the async nature of the function seems to be causing an issue. In the below editor is the LexicalEditor object.

This works fine:

editor.update( () => {
  const selection = $getSelection();
  const textContent = selection?.getTextContent();
  selection?.insertText("Some text...");
  $setSelection(null);
});

This does not work:

editor.update( async () => {
  const selection = $getSelection();
  const textContent = selection?.getTextContent();
  const textApiResponse = await fetchResponse(textContent);
  selection?.insertText(textApiResponse);
  $setSelection(null);
});

The error received is:

Uncaught (in promise) Error: Unable to find an active editor state. State helpers or node methods can only be used synchronously during the callback of editor.update() or editorState.read().

Is there a way to achieve the aim?

2

There are 2 best solutions below

0
On BEST ANSWER

I was able to solve this by lifting the text selection up out of the update, performing the request, then making the update. It will likely require disabling interactivity but it seems like a path forward. Any alternatives would be welcome.

async () => {
  const textContent = editor.getEditorState().read(() => $getSelection()?.getTextContent());
  const textApiResponse = await fetchResponse(textContent);
  editor.update(() => {
    const selection = $getSelection();
    selection?.insertText(textContent);
    $setSelection(null);
  });
}
0
On

similar problem, kinda same solution:

 const asyncFunction = async () => {
     await functionReturnsAPromise(itemAsString).then((res) => 
       setResult(res);

     editor.update(() => {
       $insertNodes([$createCustomNode(itemAsString, result)]);
       return true;
     });
  };
  asyncFunction();