React报Maximum update depth exceeded错误的原因排查
问题原因
完全不是map()渲染子组件的问题,你遇到的无限更新是状态更新逻辑形成闭环触发的,链路如下:
Maximum update depth exceeded 报错本质就是代码触发了无限循环的状态更新。
- 父组件初始渲染时如果
dataArray有初始值,会批量渲染对应的MyComponent子组件 - 每个子组件挂载完成后,依赖
data的useEffect会自动执行,调用父组件传入的save方法 save方法会执行setDataArray给原数组追加新元素,触发父组件重新渲染,dataArray长度+1- 父组件重新渲染后会多渲染一个新的
MyComponent,新组件挂载后再次执行useEffect调用save,进入无限循环,直到触达React更新深度限制。
修复方案
你需要根据自己的业务需求调整逻辑,常见的修复方向有两个:
方案1:调整父组件保存逻辑,改为更新对应下标元素
如果你是要把修改后的子组件数据同步到父组件的原数组,不要做追加操作,直接更新对应下标的元素即可:
// MainComponent 调整 saveData 逻辑 const saveData = (index, newData) => { setDataArray(prevState => { const updatedArray = [...prevState]; updatedArray[index] = newData; return updatedArray; }); } // 调用处传下标 <MyComponent data={element} index={index} save={saveData}/>
子组件调用时增加触发条件,避免初始挂载就执行更新:
// MyComponent 调整useEffect逻辑 useEffect(() => { // 只有当前数据和初始传入的props.data不一致时才触发同步,避免无效更新 if(JSON.stringify(data) !== JSON.stringify(props.data)) { props.save(props.index, data); } }, [data, props.index, props.save, props.data]);
方案2:修改保存触发时机
如果你确实需要给数组追加新元素,不要把save调用放在自动执行的useEffect里,改为用户主动触发(比如点击保存按钮):
// MyComponent 删除原来的useEffect,新增触发逻辑 const handleSave = () => { props.save(data); } return <button onClick={handleSave}>保存数据</button>
额外优化建议
如果子组件不需要维护独立于父组件的临时状态,可以直接使用props.data,不需要单独用useState存一份,减少状态同步的潜在bug。
内容的提问来源于stack exchange,提问作者BitTree
相关产品推荐
相关产品推荐

