React Native中Context传递头部节点数组引发无限重渲染的解决方法
React Native Markdown编辑器无限重渲染问题解决办法
问题根源很明确:每次组件渲染时生成的ast都是全新的数组/对象,哪怕内容完全没变,useMemo的浅比对也会判定它是新值,导致setHeaderNodes反复触发,进而带动Context更新,最终形成重渲染循环。
直接上解决方案:
实现深度比对再更新状态
自己写一个简易的深度相等判断函数,对比新旧HeaderNodes的实际内容,只有当内容真的变化时,才调用setHeaderNodes。示例代码:// 可根据你的HeaderNode结构调整这个函数 function deepEqual(a, b) { if (a === b) return true; if (typeof a !== 'object' || typeof b !== 'object' || a == null || b == null) { return false; } const keysA = Object.keys(a); const keysB = Object.keys(b); if (keysA.length !== keysB.length) return false; for (const key of keysA) { if (!keysB.includes(key) || !deepEqual(a[key], b[key])) { return false; } } return true; } // 在获取到新的headerNodes后这么用 const newHeaderNodes = extractHeaders(ast); useEffect(() => { if (!deepEqual(newHeaderNodes, headerNodes)) { setHeaderNodes(newHeaderNodes); } }, [newHeaderNodes, headerNodes]);另外,把
extractHeaders改成组件外的纯函数,或者用useCallback包裹,避免每次渲染生成新函数干扰依赖判断。修正useMemo的依赖项
之前用useMemo缓存headers时,别把ast当依赖,要依赖编辑器的原始输入文本(比如用户输入的markdown字符串)。因为ast每次都是新对象,会让useMemo白忙活。示例:const headers = useMemo(() => { const ast = parseMarkdown(text); // parseMarkdown要是纯函数 return extractHeaders(ast); }, [text]); // 只有文本变化时才重新解析生成headersContext层面控住更新
既然HeaderNodes存在Context里,只要保证只有当它实际内容变化时才更新Context,就能避免子组件(编辑器、目录菜单)跟着无意义重渲染。上面的深度比对已经能做到这一点。
内容的提问来源于stack exchange,提问作者jcubic
相关产品推荐
相关产品推荐

