Skip to content

Commit

Permalink
fix(react): attempt to cleanup editor instances, on creation #5492 (#…
Browse files Browse the repository at this point in the history
…5496)

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.
  • Loading branch information
nperez0111 authored Aug 15, 2024
1 parent 3f5dbbb commit 6a0f4f3
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/funny-terms-do.md
Original file line number Diff line number Diff line change
@@ -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
10 changes: 9 additions & 1 deletion demos/src/Extensions/CollaborationCursor/React/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
9 changes: 6 additions & 3 deletions packages/react/src/useEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
}
}

Expand Down

0 comments on commit 6a0f4f3

Please sign in to comment.