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
相关产品推荐
相关产品推荐

