mirror of
https://github.com/ueberdosis/tiptap.git
synced 2025-06-12 12:43:48 +08:00
The core of the change ended up being quite simple, because we can create the editor within the first render, we need to already schedule it's destruction. Scheduling a destruction, ensures that an instance that was created in that first render pass can be cleaned up. Waiting one more tick than before ensures that we don't accidentally destroy an editor instance that could actually be valid in the next render pass. In StrictMode, there will be two editor instances created, the first will be created & quickly destroyed in 2 ticks. In Normal React, there will only ever be 1 instance created and destroyed only on unmount.
This commit is contained in:
parent
3f5dbbbaad
commit
6a0f4f30f8
5
.changeset/funny-terms-do.md
Normal file
5
.changeset/funny-terms-do.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tiptap/react": patch
|
||||
---
|
||||
|
||||
Resolves a bug where `useEditor` may not properly cleanup an instance created when in React's StrictMode #5492
|
@ -14,7 +14,7 @@ import * as Y from 'yjs'
|
||||
const ydoc = new Y.Doc()
|
||||
const provider = new WebrtcProvider('tiptap-collaboration-cursor-extension', ydoc)
|
||||
|
||||
export default () => {
|
||||
function Component() {
|
||||
const editor = useEditor({
|
||||
extensions: [
|
||||
Document,
|
||||
@ -39,3 +39,11 @@ export default () => {
|
||||
|
||||
return <EditorContent editor={editor} />
|
||||
}
|
||||
|
||||
function App() {
|
||||
const useStrictMode = true
|
||||
|
||||
return useStrictMode ? <React.StrictMode><Component /></React.StrictMode> : <Component />
|
||||
}
|
||||
|
||||
export default App
|
||||
|
@ -78,6 +78,7 @@ class EditorInstanceManager {
|
||||
this.options = options
|
||||
this.subscriptions = new Set<() => void>()
|
||||
this.setEditor(this.getInitialEditor())
|
||||
this.scheduleDestroy()
|
||||
|
||||
this.getEditor = this.getEditor.bind(this)
|
||||
this.getServerSnapshot = this.getServerSnapshot.bind(this)
|
||||
@ -253,10 +254,10 @@ class EditorInstanceManager {
|
||||
const currentInstanceId = this.instanceId
|
||||
const currentEditor = this.editor
|
||||
|
||||
// Wait a tick to see if the component is still mounted
|
||||
// Wait two ticks to see if the component is still mounted
|
||||
this.scheduledDestructionTimeout = setTimeout(() => {
|
||||
if (this.isComponentMounted && this.instanceId === currentInstanceId) {
|
||||
// If still mounted on the next tick, with the same instanceId, do not destroy the editor
|
||||
// If still mounted on the following tick, with the same instanceId, do not destroy the editor
|
||||
if (currentEditor) {
|
||||
// just re-apply options as they might have changed
|
||||
currentEditor.setOptions(this.options.current)
|
||||
@ -269,7 +270,9 @@ class EditorInstanceManager {
|
||||
this.setEditor(null)
|
||||
}
|
||||
}
|
||||
}, 0)
|
||||
// This allows the effect to run again between ticks
|
||||
// which may save us from having to re-create the editor
|
||||
}, 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user