Skip to content

Commit

Permalink
fix(react): use ref instead of state in useEditor to prevent rerenders (
Browse files Browse the repository at this point in the history
  • Loading branch information
svenadlung authored Feb 6, 2024
1 parent 1c5c087 commit 56a5737
Showing 1 changed file with 34 additions and 35 deletions.
69 changes: 34 additions & 35 deletions packages/react/src/useEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,9 @@ import {

import { Editor } from './Editor.js'

function useForceUpdate() {
const [, setValue] = useState(0)

return () => setValue(value => value + 1)
}

export const useEditor = (options: Partial<EditorOptions> = {}, deps: DependencyList = []) => {
const [editor, setEditor] = useState<Editor | null>(null)

const forceUpdate = useForceUpdate()
const editorRef = useRef<Editor | null>(null)
const [, forceUpdate] = useState({})

const {
onBeforeCreate,
Expand All @@ -42,71 +35,77 @@ export const useEditor = (options: Partial<EditorOptions> = {}, deps: Dependency
// This effect will handle updating the editor instance
// when the event handlers change.
useEffect(() => {
if (!editor) {
if (!editorRef.current) {
return
}

if (onBeforeCreate) {
editor.off('beforeCreate', onBeforeCreateRef.current)
editor.on('beforeCreate', onBeforeCreate)
editorRef.current.off('beforeCreate', onBeforeCreateRef.current)
editorRef.current.on('beforeCreate', onBeforeCreate)

onBeforeCreateRef.current = onBeforeCreate
}

if (onBlur) {
editor.off('blur', onBlurRef.current)
editor.on('blur', onBlur)
editorRef.current.off('blur', onBlurRef.current)
editorRef.current.on('blur', onBlur)

onBlurRef.current = onBlur
}

if (onCreate) {
editor.off('create', onCreateRef.current)
editor.on('create', onCreate)
editorRef.current.off('create', onCreateRef.current)
editorRef.current.on('create', onCreate)

onCreateRef.current = onCreate
}

if (onDestroy) {
editor.off('destroy', onDestroyRef.current)
editor.on('destroy', onDestroy)
editorRef.current.off('destroy', onDestroyRef.current)
editorRef.current.on('destroy', onDestroy)

onDestroyRef.current = onDestroy
}

if (onFocus) {
editor.off('focus', onFocusRef.current)
editor.on('focus', onFocus)
editorRef.current.off('focus', onFocusRef.current)
editorRef.current.on('focus', onFocus)

onFocusRef.current = onFocus
}

if (onSelectionUpdate) {
editor.off('selectionUpdate', onSelectionUpdateRef.current)
editor.on('selectionUpdate', onSelectionUpdate)
editorRef.current.off('selectionUpdate', onSelectionUpdateRef.current)
editorRef.current.on('selectionUpdate', onSelectionUpdate)

onSelectionUpdateRef.current = onSelectionUpdate
}

if (onTransaction) {
editor.off('transaction', onTransactionRef.current)
editor.on('transaction', onTransaction)
editorRef.current.off('transaction', onTransactionRef.current)
editorRef.current.on('transaction', onTransaction)

onTransactionRef.current = onTransaction
}

if (onUpdate) {
editor.off('update', onUpdateRef.current)
editor.on('update', onUpdate)
editorRef.current.off('update', onUpdateRef.current)
editorRef.current.on('update', onUpdate)

onUpdateRef.current = onUpdate
}
}, [onBeforeCreate, onBlur, onCreate, onDestroy, onFocus, onSelectionUpdate, onTransaction, onUpdate, editor])
}, [onBeforeCreate, onBlur, onCreate, onDestroy, onFocus, onSelectionUpdate, onTransaction, onUpdate, editorRef.current])

useEffect(() => {
let isMounted = true

const instance = new Editor(options)

setEditor(instance)
editorRef.current = new Editor(options)

This comment has been minimized.

Copy link
@vinzdef

vinzdef Mar 12, 2024

const editor = new Editor(options)
editorRef.current = editor

....

return () => {
  isMounted = false
  return editor.destroy()
}

instance.on('transaction', () => {
editorRef.current.on('transaction', () => {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
if (isMounted) {
forceUpdate()
forceUpdate({})
}
})
})
Expand All @@ -119,9 +118,9 @@ export const useEditor = (options: Partial<EditorOptions> = {}, deps: Dependency

useEffect(() => {
return () => {
editor?.destroy()
return editorRef.current?.destroy()
}
}, [editor])
}, [])

This comment has been minimized.

Copy link
@vinzdef

vinzdef Mar 12, 2024

Guys this only triggers the first time. You might want to put this in the other use effect.

This has caused us quite some pain, we couldn't understand why switching editors suddenly wasn't working. Moving this in the other useEffect fixed it.


return editor
return editorRef.current
}

0 comments on commit 56a5737

Please sign in to comment.