Next.js中解决useEffect触发的Maximum update depth exceeded警告
问题诊断
控制台抛出Maximum update depth exceeded警告的核心原因是组件进入了无限重渲染死循环,代码中存在三处典型错误写法:
ListContainer组件内的useEffect没有传入依赖数组,按照React默认规则,组件每次渲染完成后都会执行该effect回调。而回调中调用了setHTML更新本地状态,状态更新会触发组件重新渲染,渲染完成后又会再次执行effect,形成闭环死循环,最终触发更新深度超限的警告。- 父子组件的数组状态更新全部直接修改了原state引用:父组件
addItem直接对原数组执行push操作、子组件delItem直接对原数组执行splice操作。React对引用类型的状态变化检测依赖引用地址变更,直接修改原内容不仅会导致状态更新判断失效,还会引发不可预期的渲染bug。 - 存在冗余的反模式状态设计:既不需要把待渲染的JSX结构存在state中,也不需要额外把props传入的items同步为本地state。React本身是状态驱动视图的框架,渲染逻辑直接在组件返回阶段执行即可,手动存储JSX到state是完全不符合React设计思路的写法。
修复代码
父组件 componentCreator 修复
修正状态更新逻辑,每次更新数组时返回全新的数组引用,不直接修改原state:
import { useState } from "react"; import AppLayout from "../components/AppLayout"; import ListContainer from "../components/ListContainer"; export default function componentCreator(){ const [item,setItem] = useState([]) /* add item to container */ function addItem(){ // 通过展开运算符创建新数组,不直接修改原item引用 const newItem = [ ...item, { produto: 'Skol 350ml', preco: '1200,00', quantidade: 'cx c/ 15 unidades' } ] setItem(newItem) } return ( <AppLayout> <ListContainer items={item} setItems={setItem}/> <div className="productcardbuttonshow" onClick={() => addItem()}>ADICIONAR</div> </AppLayout> ) }
子组件 ListContainer 修复
删除冗余状态和导致死循环的useEffect,直接基于props生成渲染内容,删除操作同样返回新数组引用:
export default function ListContainer(props){ /* remove item from container */ function delItem(id){ // 通过filter生成新数组,不直接splice修改原数组 const newItemList = props.items.filter((_, index) => index !== id) props.setItems(newItemList) } // 直接基于props生成列表JSX,数据变化时React会自动重渲染更新视图 const itemHTML = props.items.map((itemmap,id) => { return ( <div key={id} onClick={() => delItem(id)} className="itemProposta"> {itemmap.produto} - {itemmap.quantidade} - R$ {itemmap.preco} </div> ) }) return ( <> {itemHTML} </> ) }
注意:原代码中用来“刷新html容器”的useEffect完全是多余的,React会在props/state变化时自动触发重渲染,不需要手动监听数据变化再强制更新视图。
useEffect 执行机制说明
useEffect的执行时机完全由第二个参数(依赖数组)决定:
- 不传第二个参数:组件每次渲染完成后都会执行effect回调
- 传空数组
[]:仅在组件首次挂载完成后执行一次 - 传带依赖项的数组
[dep1, dep2]:首次挂载时执行一次,后续只有当数组内任意依赖项的引用发生变化时,才会再次执行effect
内容的提问来源于stack exchange,提问作者Gilberto S. Rocha
相关产品推荐
相关产品推荐

