mirror of
https://github.com/ueberdosis/tiptap.git
synced 2025-06-13 13:13:12 +08:00
fix(react): useEditor
should not destroy still mounted instances (#5338)
This forces the editor to re-use the editor instance that existed prior to an unmount and remount of the same component. This fixes a bug in `React.StrictMode` introduced with the latest performance updates by PR #5161
This commit is contained in:
parent
db0d007660
commit
1110280b2b
5
.changeset/clever-mice-search.md
Normal file
5
.changeset/clever-mice-search.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tiptap/react": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes strict mode accidentally destroying the editor instance
|
@ -93,7 +93,7 @@ function EditorInstance({ shouldOptimizeRendering }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default () => {
|
const EditorControls = () => {
|
||||||
const [shouldOptimizeRendering, setShouldOptimizeRendering] = React.useState(true)
|
const [shouldOptimizeRendering, setShouldOptimizeRendering] = React.useState(true)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -128,3 +128,11 @@ export default () => {
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
return (
|
||||||
|
<React.StrictMode>
|
||||||
|
<EditorControls />
|
||||||
|
</React.StrictMode>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -57,6 +57,7 @@ export function useEditor(
|
|||||||
options: UseEditorOptions = {},
|
options: UseEditorOptions = {},
|
||||||
deps: DependencyList = [],
|
deps: DependencyList = [],
|
||||||
): Editor | null {
|
): Editor | null {
|
||||||
|
const isMounted = useRef(false)
|
||||||
const [editor, setEditor] = useState(() => {
|
const [editor, setEditor] = useState(() => {
|
||||||
if (options.immediatelyRender === undefined) {
|
if (options.immediatelyRender === undefined) {
|
||||||
if (isSSR || isNext) {
|
if (isSSR || isNext) {
|
||||||
@ -220,12 +221,21 @@ export function useEditor(
|
|||||||
* only be called when the component is removed from the DOM, since it has no deps.
|
* only be called when the component is removed from the DOM, since it has no deps.
|
||||||
* */
|
* */
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
isMounted.current = true
|
||||||
return () => {
|
return () => {
|
||||||
|
isMounted.current = false
|
||||||
if (editor) {
|
if (editor) {
|
||||||
// We need to destroy the editor asynchronously to avoid memory leaks
|
// We need to destroy the editor asynchronously to avoid memory leaks
|
||||||
// because the editor instance is still being used in the component.
|
// because the editor instance is still being used in the component.
|
||||||
|
|
||||||
setTimeout(() => (editor.isDestroyed ? null : editor.destroy()))
|
setTimeout(() => {
|
||||||
|
// re-use the editor instance if it hasn't been destroyed yet
|
||||||
|
// and the component is still mounted
|
||||||
|
// otherwise, asynchronously destroy the editor instance
|
||||||
|
if (!isMounted.current && !editor.isDestroyed) {
|
||||||
|
editor.destroy()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
Loading…
Reference in New Issue
Block a user