Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Issue with flushSync Error when Using addNodeView() in Next.js with Tiptap #4355

Closed
2 tasks done
totorofly opened this issue Aug 19, 2023 · 9 comments
Closed
2 tasks done
Labels
Category: Open Source The issue or pull reuqest is related to the open source packages of Tiptap. Type: Bug The issue or pullrequest is related to a bug

Comments

@totorofly
Copy link

Which packages did you experience the bug in?

nextjs

What Tiptap version are you using?

2.1.1

What’s the bug you are facing?

When using the addNodeView() method with a ReactNodeViewRenderer component in conjunction with the tiptap library within a Next.js project, an error is encountered during runtime. The error message indicates that flushSync was called from inside a lifecycle method, causing React to be unable to flush while rendering is already ongoing. This error disappears when the addNodeView() method is removed.

Steps to Reproduce:

  1. Integrate the provided addNodeView() code with the ReactNodeViewRenderer component into a Next.js project.
  2. Attempt to render the editor containing the custom node view.

Expected Behavior:
The editor should render without any errors or warnings related to flushSync.

Actual Behavior:
An error occurs with the following warning message:
Warning: flushSync was called from inside a lifecycle method. React cannot flush when React is already rendering. Consider moving this call to a scheduler task or micro task.

Relevant Code:

import { mergeAttributes, Node } from '@tiptap/core'
import Component from '../components/nodeView/ParagraphNodeView';
import {ReactNodeViewRenderer} from "@tiptap/react";

export interface ParagraphOptions {
    HTMLAttributes: Record<string, any>,
}

declare module '@tiptap/core' {
    interface Commands<ReturnType> {
        paragraph: {
            /**
             * Toggle a paragraph
             */
            setParagraph: () => ReturnType,
        }
    }
}

export default Node.create<ParagraphOptions>({
    name: 'paragraph',

    priority: 1000,

    addOptions() {
        return {
            HTMLAttributes: {},
        }
    },

    group: 'block',

    content: 'inline*',

    parseHTML() {
        return [
            { tag: 'p' },
        ]
    },

    renderHTML({ HTMLAttributes }) {
        return ['p', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]
    },

    addCommands() {
        return {
            setParagraph: () => ({ commands }) => {
                return commands.setNode(this.name)
            },
        }
    },

    addKeyboardShortcuts() {
        return {
            'Mod-Alt-0': () => this.editor.commands.setParagraph(),
        }
    },

    addNodeView() {
        return ReactNodeViewRenderer(Component);
    },
})
'use client';
import React from 'react';
import {NodeViewContent, NodeViewWrapper} from '@tiptap/react';

const ParagraphNodeView: React.FC = () => {
    return (
        <NodeViewWrapper style={{"border": "1px solid red"}}>
            <NodeViewContent as={"p"} ></NodeViewContent>
        </NodeViewWrapper>
    );
};

export default ParagraphNodeView;

What browser are you using?

Edge

Code example

No response

What did you expect to happen?

The editor should render without any errors or warnings related to flushSync.

Anything to add? (optional)

The issue seems to be related to the interaction between the addNodeView() method and React's rendering mechanism in a Next.js project.
Removing the addNodeView() code resolves the issue.

Did you update your dependencies?

  • Yes, I’ve updated my dependencies to use the latest version of all packages.

Are you sponsoring us?

  • Yes, I’m a sponsor. 💖
@totorofly totorofly added Category: Open Source The issue or pull reuqest is related to the open source packages of Tiptap. Type: Bug The issue or pullrequest is related to a bug labels Aug 19, 2023
@github-project-automation github-project-automation bot moved this to Triage open in Tiptap Aug 19, 2023
@tscritch
Copy link

I am experiencing this same error in a Vite React app. It only appears when HMR refreshes (ie saving a file). This could be a duplicate issue though: #3580

@totorofly
Copy link
Author

I am experiencing this same error in a Vite React app. It only appears when HMR refreshes (ie saving a file). This could be a duplicate issue though: #3580

This problem does indeed seem quite awkward, although it currently doesn't seem to have any effect on the actual results.

@totorofly
Copy link
Author

The performance of ReactNodeView deteriorates significantly as the number of lines increases, whereas the Vue version of NodeView performs quite normally.

@totorofly
Copy link
Author

In my situation, I was experiencing poor performance and lag as the number of lines in a Paragraph node with a NodeView increased. This significantly impacted the user experience during text input. However, when I changed the maybeFlushSync(fn: () => void) method from:

if (this.initialized) {
  flushSync(fn);
} else {
  fn();
}

to:

if (this.initialized) {
  fn();
} else {
  fn();
}

The lag and performance issues were resolved. I am just not sure what potential risks this change might introduce.

@wasular
Copy link

wasular commented Sep 1, 2023

I experience the same issue , hopefully this will be fixed soon

@lgatibel
Copy link

i think tiptap editor try to sync with the dom update so for now here my temporary solution:

useEffect(() => {
        if (editorInstance && initialContent) {
            setTimeout(() => {
                editorInstance.commands.setContent(initialContent)
            }, 1000)
        }
    }, [editorInstance, initialContent])

Instead of

useEffect(() => {
        if (editorInstance && initialContent) {
            setTimeout(() => {
                editorInstance.commands.setContent(initialContent)
            })
        }
    }, [editorInstance, initialContent])

@zakwear
Copy link

zakwear commented Jun 8, 2024

This is the only config that works for us:

const CustomNode = dynamic(() => import("./CustomNode"), { ssr: false });
addNodeView() {
return ReactNodeViewRenderer(CustomNode);
}

@Ecaratti
Copy link

Fwiw, I had flushSync issues when adding nodeViewRenderes (react), turns out the issue spawned from conditionally rendering the EditorContent in my main Editor component (so the issue wasn't in any nodeView components)

const [isSynched, setIsSynched] = useState(false)
.const {editor} = useEditor(...)
...

return (

{isSynched ? ( ) : ( )} ...
) Removing the conditionality solved it for me.

@nperez0111
Copy link
Contributor

This should be fixed in Tiptap 2.9

@github-project-automation github-project-automation bot moved this from Triage open to Done in Tiptap Nov 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Category: Open Source The issue or pull reuqest is related to the open source packages of Tiptap. Type: Bug The issue or pullrequest is related to a bug
Projects
No open projects
Archived in project
Development

No branches or pull requests

9 participants