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

为何下述ReactJS代码会触发无限重渲染循环?

问题描述

原本期望在__payload变化时执行useEffect的代码:

const Viewer = (props) => { 
    
    const __payload = JSON.parse(props.payload);    
    const [values, setValues] = useState([]);
    
    useEffect( () => { 
        var __values = "value"; // 传入字符串
        setValues(__values);
    }, [__payload]);
};

但当向setValues传入数组值时,出现无限循环并抛出错误:

const Viewer = (props) => { 
    
    const __payload = JSON.parse(props.payload);    
    const [values, setValues] = useState([]);
    
    useEffect( () => { 
        var __values = ["value"]; // 传入数组
        setValues(__values);
    }, [__payload]);
};

错误提示:

Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.

明明已经限定useEffect仅在__payload变化时执行,为何会出现这种情况?


原因分析

核心问题出在__payload的创建方式和React依赖比较的逻辑上:

  • 引用类型与基本类型的比较差异:
    React检查useEffect依赖时使用Object.is规则:字符串这类基本类型只要值相等,就会被判定为相同;但数组、对象这类引用类型,哪怕内容完全一致,只要是不同的内存引用,就会被判定为不同。

  • 每次渲染都会生成新的__payload引用:
    不管props.payload有没有变化,每次组件渲染时,JSON.parse(props.payload)都会返回全新实例:

    • 如果解析结果是字符串,值相同的情况下Object.is判定为相等,useEffect不会重复执行;
    • 如果解析结果是数组/对象,每次都是新的引用,React会认为__payload每次都变了,于是反复触发useEffect。
  • 无限循环触发链:
    useEffect执行 → 调用setValues更新状态 → 组件重新渲染 → 生成新的__payload引用 → useEffect再次触发 → 循环往复,最终超出渲染深度限制。


解决办法

方法1:用useMemo缓存解析后的__payload

把解析操作包裹在useMemo里,只在props.payload变化时重新解析,保证__payload的引用稳定:

const Viewer = (props) => { 
    const __payload = useMemo(() => JSON.parse(props.payload), [props.payload]);    
    const [values, setValues] = useState([]);
    
    useEffect( () => { 
        var __values = ["value"];
        setValues(__values);
    }, [__payload]);
};

方法2:直接依赖props.payload

既然__payload是从props.payload解析而来,可跳过中间变量,直接把props.payload作为useEffect的依赖,只有当原字符串变化时才触发:

const Viewer = (props) => { 
    const [values, setValues] = useState([]);
    
    useEffect( () => { 
        const __payload = JSON.parse(props.payload);
        var __values = ["value"];
        setValues(__values);
    }, [props.payload]);
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 08:25:14