QuillJS selection-change事件回调缓存变量导致状态值不更新如何解决
问题原因
这是典型的React闭包陷阱问题,和Quill事件缓存无关:你当前的useEffect仅设置了quill作为依赖项,只会在quill实例初始化时执行一次,内部注册的selection-change事件回调会捕获作用域内的初始documentState快照,后续documentState更新后,回调内访问的依旧是初始化时的旧值。
解决方案
方案1:补充依赖项+添加事件清理逻辑
把相关状态加入依赖数组,同时在useEffect返回值中添加事件解绑逻辑,避免重复注册事件:
useEffect(() => { if (!quill) return quill.clipboard.dangerouslyPasteHTML(documentContent); const handleTextChange = () => { setDocumentContent(quill.root.innerHTML); } const handleSelectionChange = (range, oldRange, source) => { console.log(documentState?.predictionStatus, range, oldRange, source); } quill.on('text-change', handleTextChange); quill.on('selection-change', handleSelectionChange); // 依赖变化时清理旧事件监听器 return () => { quill.off('text-change', handleTextChange); quill.off('selection-change', handleSelectionChange); } }, [quill, documentState, documentContent]);
方案2:用useRef存储最新状态,避免重复绑定事件
如果不想频繁触发Quill事件的解绑/绑定,可以用ref同步最新的状态值:
// 组件内声明ref同步最新的documentState const documentStateRef = useRef(documentState); // 每次documentState更新时同步ref的值 useEffect(() => { documentStateRef.current = documentState; }, [documentState]); // 原quill初始化useEffect仅需修改回调取值逻辑 useEffect(() => { if (quill) { quill.clipboard.dangerouslyPasteHTML(documentContent); quill.on('text-change', () => { setDocumentContent(quill.root.innerHTML); }); quill.on('selection-change', (range, oldRange, source) => { // 读取ref的最新值,不受闭包影响 console.log(documentStateRef.current?.predictionStatus, range, oldRange, source); }) } }, [quill, documentContent]);
该方案只会在quill初始化时注册一次事件,性能开销更低。
内容的提问来源于stack exchange,提问作者Shamoon
相关产品推荐
相关产品推荐

