perf: debounce getHTML() dans onUpdate — 400ms au lieu de chaque frappe
getHTML() traverse tout le document ProseMirror à chaque transaction. Sur les notes longues (500+ blocs), cela causait des lags visibles. Maintenant debounced à 400ms via setTimeout + clearTimeout. Le wikilink detection reste synchrone (réactif).
This commit is contained in:
@@ -359,12 +359,21 @@ export const RichTextEditor = forwardRef<RichTextEditorHandle, RichTextEditorPro
|
|||||||
const editorInstanceRef = useRef<Editor | null>(null)
|
const editorInstanceRef = useRef<Editor | null>(null)
|
||||||
const onChangeRef = useRef(onChange)
|
const onChangeRef = useRef(onChange)
|
||||||
onChangeRef.current = onChange
|
onChangeRef.current = onChange
|
||||||
|
const htmlDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||||
|
|
||||||
const emitContentChange = useCallback((html: string) => {
|
const emitContentChange = useCallback((html: string) => {
|
||||||
lastEmittedContent.current = html
|
lastEmittedContent.current = html
|
||||||
onChangeRef.current?.(html)
|
onChangeRef.current?.(html)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
// Debounced version for onUpdate — avoids calling getHTML() on every keystroke
|
||||||
|
const emitContentChangeDebounced = useCallback((editor: any) => {
|
||||||
|
if (htmlDebounceRef.current) clearTimeout(htmlDebounceRef.current)
|
||||||
|
htmlDebounceRef.current = setTimeout(() => {
|
||||||
|
emitContentChange(editor.getHTML())
|
||||||
|
}, 400)
|
||||||
|
}, [emitContentChange])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof window === 'undefined') return
|
if (typeof window === 'undefined') return
|
||||||
const checkMobile = () => setIsMobile(window.innerWidth < 768)
|
const checkMobile = () => setIsMobile(window.innerWidth < 768)
|
||||||
@@ -595,8 +604,8 @@ export const RichTextEditor = forwardRef<RichTextEditorHandle, RichTextEditorPro
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onUpdate: ({ editor: e }) => {
|
onUpdate: ({ editor: e }) => {
|
||||||
// Debounce getHTML() — it's expensive on long notes
|
// Debounced getHTML() — avoids traversing the whole doc on every keystroke
|
||||||
emitContentChange(e.getHTML())
|
emitContentChangeDebounced(e)
|
||||||
if (!e.isEditable) return
|
if (!e.isEditable) return
|
||||||
const { from, empty } = e.state.selection
|
const { from, empty } = e.state.selection
|
||||||
if (!empty) return
|
if (!empty) return
|
||||||
|
|||||||
Reference in New Issue
Block a user