steven-tey / novel

Notion-style WYSIWYG editor with AI-powered autocompletion.
https://novel.sh
Apache License 2.0
12.7k stars 1.04k forks source link

Can't access to the editor instance to change content programmatically #380

Closed InharAldalur closed 5 months ago

InharAldalur commented 5 months ago

Describe the feature you'd like to request

I want to change the editor's content programmatically but I can't use editor.commands.setContent() outside EditorRoot. And the hook useEditor doesn't work to get the instance.

How could I solve this? I can't see any prop to do so. There is onUpdate prop to but I want to change the content when a button is clicked.

Thank you so much :)

Describe the solution you'd like to see

I'd like to use editor.commands.setContent() in my code and change the content. But is impossible to get the editor's instance.

Thank you :)

Additional information

No response

hellskater commented 5 months ago

Recently faced the same issue. I got it working in a very hacky way, until novel supports it natively.

So basically, in the component where I'm rendering EditorContent, there is an early return like this

if (!initialContent) null

The issue is initialContent doesn't respond to changes for obvious reasons. And what works in this case is, setting the initialContent to null before changing. In my case, something like this

flushSync(() => {
   setSelectedNote(null);
 });

setSelectedNote(noteId);

Since initialContent prop is derived from the selectedNote state, that also becomes null and the editor content changes on the next render.

InharAldalur commented 5 months ago

Recently faced the same issue. I got it working in a very hacky way, until novel supports it natively.

So basically, in the component where I'm rendering EditorContent, there is an early return like this

if (!initialContent) null

The issue is initialContent doesn't respond to changes for obvious reasons. And what works in this case is, setting the initialContent to null before changing. In my case, something like this

flushSync(() => {
   setSelectedNote(null);
 });

setSelectedNote(noteId);

Since initialContent prop is derived from the selectedNote state, that also becomes null and the editor content changes on the next render.

This approach worked!

Instead of flushSync I used a short setTimeout to update the states in the same useEffect without React warnings.

Thank you so much! You saved me!