You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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]); // 只有文本变化时才重新解析生成headers
    
  • Context层面控住更新
    既然HeaderNodes存在Context里,只要保证只有当它实际内容变化时才更新Context,就能避免子组件(编辑器、目录菜单)跟着无意义重渲染。上面的深度比对已经能做到这一点。

内容的提问来源于stack exchange,提问作者jcubic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:42:19