Closed chasinhues closed 3 years ago
Did you try upgrading all your dependencies? The core is at beta.81 already.
Same issue on my end
Updated all my dependencies to the latests to try out, the issue still shows up.
For me it starts at "@tiptap/react": "^2.0.0-beta.43",
which introduces the dependency array for the editor.
Thanks for the suggestion. Issue still persists using:
"@tiptap/core@^2.0.0-beta.81"
"@tiptap/react@^2.0.0-beta.46"
"@tiptap/starter-kit@^2.0.0-beta.77"
@chasinhues is there any workaround?
Not that I'm aware of
@chasinhues I hope the following would help spotting the root cause.
This issue happens to me in editor.setContent() after hot-reload and when creating an editor dynamically, it also happens when dynamically adding multiple editors without delay. If I wait for a second after creating an editor before re-creating another one, it doesn't occur.
It seems that successive dynamic creation error is due to setTimeout(() => editor.createNodeViews(), 0) in EditorContent. I also suspect that this error causes the setContent() one too.
I added try-catch around setContent() with 3 retries separated by a delay of 100ms. However, the createNodeViews() does not seem to be catchable from the component.
Is there any chance of a hotfix to prevent this uncaught error from propagating since the software will be shipped soon :( ?
We're hitting this and have updated our dependencies to all the latest tiptap versions as of 2 days ago (see below):
This may be happening when we destroy the editor and then recreate it again. Is there any guidance on timing for destroying the editor before instantiating a new one?
➜ client git:(main) yarn info @tiptap/core @tiptap/react
├─ @tiptap/core@npm:2.0.0-beta.84
│ ├─ Version: 2.0.0-beta.84
│ │
│ └─ Dependencies
│ ├─ @types/prosemirror-commands@npm:^1.0.4 → npm:1.0.4
│ ├─ @types/prosemirror-inputrules@npm:^1.0.4 → npm:1.0.4
│ ├─ @types/prosemirror-keymap@npm:^1.0.4 → npm:1.0.4
│ ├─ @types/prosemirror-model@npm:^1.13.0 → npm:1.13.0
│ ├─ @types/prosemirror-schema-list@npm:^1.0.3 → npm:1.0.3
│ ├─ @types/prosemirror-state@npm:^1.2.6 → npm:1.2.6
│ ├─ @types/prosemirror-transform@npm:^1.1.3 → npm:1.1.3
│ ├─ @types/prosemirror-view@npm:^1.17.1 → npm:1.17.1
│ ├─ prosemirror-commands@npm:^1.1.9 → npm:1.1.9
│ ├─ prosemirror-inputrules@npm:^1.1.3 → npm:1.1.3
│ ├─ prosemirror-keymap@npm:^1.1.3 → npm:1.1.4
│ ├─ prosemirror-model@npm:^1.14.2 → npm:1.14.2
│ ├─ prosemirror-schema-list@npm:^1.1.4 → npm:1.1.4
│ ├─ prosemirror-state@npm:^1.3.4 → npm:1.3.4
│ ├─ prosemirror-transform@npm:^1.3.2 → npm:1.3.2
│ └─ prosemirror-view@npm:^1.18.7 → npm:1.18.7
│
└─ @tiptap/react@npm:2.0.0-beta.50
├─ Instances: 1
├─ Version: 2.0.0-beta.50
│
└─ Dependencies
├─ @tiptap/extension-bubble-menu@npm:^2.0.0-beta.23 → npm:2.0.0-beta.23
├─ @tiptap/extension-floating-menu@npm:^2.0.0-beta.17 → npm:2.0.0-beta.17
└─ prosemirror-view@npm:^1.18.7 → npm:1.18.7
This patch should fix that error.
@philippkuehn Thank you for the patch! I noticed that the same error also occurs on setContent after React's Fast Refresh.
Yeah I'm still noticing this as obezzad mentioned, even after upgrading to the patch with the fix.
I noticed that the same error also occurs on setContent after React's Fast Refresh.
We were able to hack around this by adding checks for editor.isDestroyed
in our useEffect hooks like so:
Could we update editor.commands to do this check automatically, and never try to run a command when the editor itself is destroyed? That might catch a lot of issues.
However, even after adding this, hot reload still triggered an error in the Yjs sync plugin, see screenshot below. It looks like that can also be suppressed by adding // @refresh reset
at the top of the file where we load the Collaboration plugin. This is a NextJS directive, not sure if there are equivalents elsewhere.
@thatsjonsense Thank you for the workaround. I believe all the matchesNode errors are due editor.isDestroyed not checked. This may not be an issue in Vue, but React seems to work differently.
@philippkuehn Can you re-open this issue, or should we create another issue and refer to this one?
The CollaborationCursorPlugin throws the same error in some circumstances. We use the react TipTap package with the collab feature. Our editor can be opened and closed within our application - the open/close state is synced with all currently connected clients via websocket.
The error occurs when a user is still inside the editor, while the editor is closed by someone else. The root cause is the same as described here: https://github.com/ueberdosis/tiptap/issues/438#issuecomment-887586064
I have the same issue with BubbleMenu
component that comes with @tiptap/react
, it crashes when Fast Refresh is triggered. From what I understood from this conversation, the lack of editor.isDestroyed
check causes that, so I changed this part in useEffect
of BubbleMenu
component (locally, in node_modules :smile:) and it seems to work:
if (!editor.isDestroyed) {
editor.registerPlugin(BubbleMenuPlugin({
pluginKey,
editor,
element: element.current as HTMLElement,
tippyOptions,
shouldShow,
}))
}
However it would probably make more sense to check it in registerPlugin
considering a similar check is present in unregisterPlugin
. Changing it in BubbleMenu
seems like lower risk change, though. I can prepare a PR, but I'd rather have an opinion where it should be fixed as I'm completely unfamiliar with the codebase.
This patch should fix that error.
useEffect(() => {
if (editor && !editor.isDestroyed) {
editor.chain().focus().setContent(content).run();
}
}, [content, editor]);
can solve this problem.
Hey @philippkuehn, I think I've found a more general solution to this that prevents the error. A little hacky but let me know what you think
import { EditorView } from 'prosemirror-view'
EditorView.prototype.updateState = function updateState(state) {
if (!this.docView) return // This prevents the matchesNode error on hot reloads
this.updateStateInner(state, this.state.plugins != state.plugins)
}
@thatsjonsense Really a bit hacky :) Do you still see this error? Haven't seen it for ages.
Yep, all the time :( I believe it’s coming from inside the collaboration plug-ins during hot reload. They try to update some stage after the editor is destroyed, before it is recreated
On Fri, Oct 29, 2021 at 1:02 AM Philipp Kühn @.***> wrote:
@thatsjonsense https://github.com/thatsjonsense Really a bit hacky :) Do you still see this error? Haven't seen it for ages.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ueberdosis/tiptap/issues/1451#issuecomment-954519094, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAQ5BWPHVOPIFENHMWJ7UXLUJJPKBANCNFSM46P7VDZA .
-- Jon Noronha Cofounder, Gamma
I also see this regularly. I am using Snowpack with HMR and Fast Refresh. (https://www.snowpack.dev/concepts/hot-module-replacement) I have a React app with a component that wraps TipTap named <TipTapText/>
in TipTapText.tsx
. Each time I save that file and it HMR/Fast Refreshes, I see this error.
Adding the lines from @thatsjonsense 's comment above to TipTapText.tsx
fixes the issue for me.
Versions:
$ grep tiptap package.json
"@tiptap/extension-collaboration": "^2.0.0-beta.31",
"@tiptap/extension-collaboration-cursor": "^2.0.0-beta.31",
"@tiptap/extension-placeholder": "^2.0.0-beta.44",
"@tiptap/html": "^2.0.0-beta.142",
"@tiptap/react": "^2.0.0-beta.95",
"@tiptap/starter-kit": "^2.0.0-beta.145",
Experienced this as well. Not hot-reloading. Also using multiple editors on the same page. Hack by @thatsjonsense worked for me.
I modified the code by @thatsjonsense to reuse the old updateState:
import { EditorView } from 'prosemirror-view';
const oldUpdateState = EditorView.prototype.updateState;
EditorView.prototype.updateState = function (state) {
// This prevents the matchesNode error on hot reloads
if (!this.docView) {
return;
}
oldUpdateState.call(this, state);
};
This bug was apparently fixed in y-prosemirror@1.1.0, but this same version introduced another issue: https://github.com/yjs/y-prosemirror/issues/117
So I had to downgrade to y-prosemirror@1.0.20 and this problem still exists there.
For me the error also came with a modal function where the editor was not visible.
I solved the problem by checking if the plugins are loaded.
export const resetContent = () => {
if (editor.view.pluginViews.length) {
editor.commands.clearContent();
}
};
I'm still getting this issue in development, for me it occurs when my styled component wrapper gets resaved - it triggers the error. I've gotten around it by extracting editor explicitly into its own component and passing back to the parent component that has the styled component wrapper.
using: vite": "^3.0.7", "@tiptap/react": "^2.0.0-beta.114", "@tiptap/starter-kit": "^2.0.0-beta.191", "styled-components": "^5.3.5",
react-dom.development.js:22839 Uncaught TypeError: Cannot read properties of null (reading 'matchesNode')
at EditorView.updateStateInner (index.js:4913:49)
at EditorView.update (index.js:4868:14)
at EditorView.setProps (index.js:4882:14)
at Editor2.createNodeViews (Editor.ts:299:15)
at PureEditorContent.init (EditorContent.tsx:67:14)
at PureEditorContent.componentDidMount (EditorContent.tsx:42:10)
at invokeLayoutEffectMountInDEV (react-dom.development.js:25133:22)
at invokeEffectsInDev (react-dom.development.js:27351:11)
at commitDoubleInvokeEffectsInDEV (react-dom.development.js:27327:5)
at flushPassiveEffectsImpl (react-dom.development.js:27056:5)
This error also seems to be triggered by StrictMode, because the component is immediatly unmounted and remounted.
From time to time we are experiencing the same issue, this workaround https://github.com/ueberdosis/tiptap/issues/1451#issuecomment-953348865 works well, but is there any other recommendations since then? Thanks
It's not completely tiptap-relateded, but I had this issue because I implemented an asynchronous ProseMirror plugin.
If I closed the editor before the asynchronous call resolved, the program tried to update a view that didn't exist anymore.
My code was something like that:
asynchronousApiCall().then(data => {
// this could happen after my editor is closed
view.dispatch(view.state.tr.setMeta("call resolved", data)
})
And I added the following check:
asynchronousApiCall().then(data => {
// check if the editor is still alive
if (!(view as any)?.docView) return
view.dispatch(view.state.tr.setMeta("call resolved", data)
})
I encountered this issue when adding dependencies to useEditor
from @tiptap/react
. I'm running "@tiptap/react": "^2.0.0-beta.199"
If I don't add the dependencies to the array I don't get this error when I have multiple editors on the same page. As I add deps to get it to react to being moved/destroyed I get this error. I
I used https://github.com/ueberdosis/tiptap/issues/1451#issuecomment-941988769 solution and removing the dependency array. This seems like a bug to me, I'm just getting a less granular solution to what I assume useEditor does under the hood.
I encountered this issue when adding dependencies to
useEditor
from@tiptap/react
. I'm running"@tiptap/react": "^2.0.0-beta.199"
If I don't add the dependencies to the array I don't get this error when I have multiple editors on the same page. As I add deps to get it to react to being moved/destroyed I get this error. I
I used #1451 (comment) solution and removing the dependency array. This seems like a bug to me, I'm just getting a less granular solution to what I assume useEditor does under the hood.
It has been almost two years and there is no solution in sight.
I've just followed the official documentation for installing TipTap into NextJS and got this bug. Latest TipTip and NextJS. I just copy pasted the example code without adding anything.
I tried all fixes and nothing seems to work. (I'm not sure if I was doing correctly.) Whenever I change something in the component I see this error in the browser.
Is there any other was I could make this work?
@vaetas Assuming your issue is caused by the same root cause as the issue I submitted, it was fixed in v2.0.0-beta.220!
We were able to hack around this by adding checks for
editor.isDestroyed
in our useEffect hooks like so:Could we update editor.commands to do this check automatically, and never try to run a command when the editor itself is destroyed? That might catch a lot of issues.
However, even after adding this, hot reload still triggered an error in the Yjs sync plugin, see screenshot below. It looks like that can also be suppressed by adding
// @refresh reset
at the top of the file where we load the Collaboration plugin. This is a NextJS directive, not sure if there are equivalents elsewhere.
This was ultimately the only thing that solved the problem for us. Echoing the question by @thatsjonsense: is this something that is possible for TipTap to check internally when commands are executing against an instance of the editor?
We were able to hack around this by adding checks for
editor.isDestroyed
in our useEffect hooks like so: Could we update editor.commands to do this check automatically, and never try to run a command when the editor itself is destroyed? That might catch a lot of issues. However, even after adding this, hot reload still triggered an error in the Yjs sync plugin, see the screenshot below. It looks like that can also be suppressed by adding// @refresh reset
at the top of the file where we load the Collaboration plugin. This is a NextJS directive, not sure if there are equivalents elsewhere.This was ultimately the only thing that solved the problem for us. Echoing the question by @thatsjonsense: is this something that is possible for TipTap to check internally when commands are executing against an instance of the editor?
Did you open a PR for it?
I don't think they are planning to fix this.
This error also seems to be triggered by StrictMode, because the component is immediatly unmounted and remounted.
The remix app was also giving an error on every hot reload due to StrictMode, removing StrictMode worked fine. But I guess that doesn't make sense for StrictMode, lol.
I am using Remix v2 and have the same problem on every hot reload. I use useEditor(). I did not see a solution/workaround for people using that hook, maybe someone solved this though?
Hey @philippkuehn, I think I've found a more general solution to this that prevents the error. A little hacky but let me know what you think
import { EditorView } from 'prosemirror-view' EditorView.prototype.updateState = function updateState(state) { if (!this.docView) return // This prevents the matchesNode error on hot reloads this.updateStateInner(state, this.state.plugins != state.plugins) }
where do you put this line?
I am getting following error . Property 'docView' does not exist on type 'EditorView'
& Property 'updateStateInner' is private and only accessible within class 'EditorView'
Hey @philippkuehn, I think I've found a more general solution to this that prevents the error. A little hacky but let me know what you think
import { EditorView } from 'prosemirror-view' EditorView.prototype.updateState = function updateState(state) { if (!this.docView) return // This prevents the matchesNode error on hot reloads this.updateStateInner(state, this.state.plugins != state.plugins) }
where do you put this line? I am getting following error .
Property 'docView' does not exist on type 'EditorView'
&Property 'updateStateInner' is private and only accessible within class 'EditorView'
https://codesandbox.io/p/sandbox/tiptap-newline-error-kpgm8?file=%2Fsrc%2FApp.tsx%3A6%2C10-6%2C20
Experienced this as well. Not hot-reloading. Also using multiple editors on the same page. Hack by @thatsjonsense worked for me.
Hello, can you kindly explain to me exactly where I need to apply the codes? I am lost and I see this error.
got the same error today when trying to update from 2.2.4 to 2.4.0 . workaround didn’t solve it, so switched back to 2.2.5, which is the latest version which works for me.
using multiple editors on the same page as others also mentioned.
Description
Same issue as in https://github.com/ueberdosis/tiptap/issues/438. TypeError that crashes my app.
Steps to reproduce the bug
Happens on occasion when navigating to a page with a TipTap editor on it.
CodeSandbox
In the CSB below, run the tests, and observe the console spits out a bunch of these type errors for the browser. I don't know why it does this...
https://codesandbox.io/s/tiptap-prose-matchesnode-error-yhvdc
Expected behavior
No error.
Environment?
@tiptap/core@^2.0.0-beta.65
Additional context
I tried to keep the CSB example above as close to my current code as possible, minus other third-party libraries that would unnecessarily bloat the example.
I am able to replicate the error consistently in my tests: