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

React新手求助:如何避免useEffect中调用useState触发无限重渲染?

解决React useEffect无限重渲染问题

问题根源

你的useEffect依赖数组里包含了equipmentState,但每次调用setEquipmentState都会修改这个状态值,触发useEffect重新执行,形成无限循环。同时,你用[...equipmentState, itemID]这种方式更新状态时,依赖了当前的equipmentState,如果直接移除这个依赖,又可能拿到旧状态,所以得改用函数式更新来规避这个问题。

解决方案步骤

  • 移除equipmentState依赖:把它从useEffect的依赖数组里删掉,避免状态更新触发重复执行。
  • 统一用函数式更新状态:不管是添加还是移除操作,都用setEquipmentState(current => ...)的形式,这样不需要依赖当前的equipmentState,也能拿到最新的状态值。
  • 调整依赖数组匹配需求:如果只需要页面加载时执行一次,把依赖数组改成[];如果myPlace.remove和myPlace.add变化时需要重新执行逻辑,就保留这两个依赖(注意要确保它们是稳定值,比如基本类型,不是每次渲染都生成新引用的对象/数组)。

修改后的代码

useEffect(() => {
    const addOrRemoveEquipment = (itemID, action) => {
        if (itemID && action) {
            if (action === "add") {
                // 改用函数式更新,获取最新状态
                setEquipmentState(current => [...current, itemID]);
            } else if (action === "remove") {
                setEquipmentState((current) =>
                    current.filter((item) => item !== itemID[0])
                );
            }
        }
    };

    const addOrRemoveItem = (val) => {
        if (val instanceof Array) {
            addOrRemoveEquipment(val[1], "add");
            addOrRemoveEquipment(val[0], "remove");
        }
    };

    addOrRemoveItem([myPlace.remove, myPlace.add]);

    return () => {
        // 组件卸载时执行反向操作,注意这里参数顺序调换,恢复初始状态
        addOrRemoveItem([myPlace.add, myPlace.remove]);
    };
    // 若仅页面加载执行一次,替换为[];若myPlace相关值变化需重新执行,保留现有依赖
}, [myPlace.remove, myPlace.add, setEquipmentState]);

额外注意点

  • 如果myPlace.remove或myPlace.add是对象/数组这类复杂类型,每次渲染会生成新引用,导致useEffect意外触发。这种情况需要用useMemo包裹这些值,或者在依赖里比较其内部的具体属性。
  • 如果你明确只需要页面加载时执行一次状态修改,直接把依赖数组改成[]即可,这样useEffect只会在组件挂载时执行一次。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 18:46:12