React分页时Too Many Re-renders无限循环问题求解
问题根因
你遇到的无限循环,核心是两个违反React运行规则的写法叠加出来的:
- 直接在组件的渲染函数体(也就是函数组件的同步执行逻辑)里调用
setPageInfo - 拉取jobInfo的effect和本地pageInfo状态形成了双向触发的依赖闭环
具体修复步骤
1. 移除渲染阶段的副作用逻辑
React的组件渲染阶段必须是纯函数,不能在这个阶段执行任何状态更新操作——你现在在if (!loading && jobInfo)的判断里直接调setPageInfo,只要这个判断成立,每次组件渲染都会触发一次状态更新,状态更新又会触发下一轮渲染,单这一个写法就足够形成无限循环。
所有需要在状态变化后执行的同步、异步操作,都应该放到useEffect中,同时要加上值对比逻辑,避免相同值的重复更新:
useEffect(() => { if (!loading || !jobInfo) return; // 对比新旧值,相同则直接返回旧状态,跳过更新 setPageInfo(prev => { const isSameValue = prev.pageSize === jobInfo.count && prev.currentPage === jobInfo.page; return isSameValue ? prev : { pageSize: jobInfo.count, currentPage: jobInfo.page } }) }, [loading, jobInfo])
这种写法的好处是,就算effect的依赖变化,只要要设置的状态值和当前值一模一样,React会直接跳过这次渲染,从根源上断掉循环链路。
2. 砍掉冗余的本地状态
检查你现有代码会发现:你初始化了本地的pageInfo状态,但渲染分页组件、计算分页数据的时候,全程没有读取过这个本地状态的值,反而所有参数都是直接从上下文的jobInfo里取的。
完全可以把这个多余的useState直接删掉,所有分页相关的参数(当前页码、每页条数、总数据量)直接从jobInfo上下文里读取。少维护一个多余的本地状态,就少一个可能触发循环的入口。
3. 梳理单向的状态流
你现在的双向循环本质是状态流乱了:pageInfo的更新会触发jobInfo重新拉取,jobInfo更新又反过来触发pageInfo更新。正确的分页状态流应该是完全单向的:
- 用户点击分页组件的页码 -> 调用useContext拿到的dispatch方法,更新jobInfo接口的请求页码参数
- 请求参数变化 -> 触发拉取jobInfo的effect,请求对应页的接口数据
- 接口返回数据 -> 更新上下文中的jobInfo状态
- 组件接收到新的jobInfo状态,渲染对应页的表格、分页组件
整个流程里没有需要本地维护的分页状态,自然不会出现双向触发的问题。
4. 修正其他容易触发多余重渲染的细节
- 现在渲染表格行的时候用
uuid()当key,每次渲染都会生成随机的key值,会让React每次都卸载、重建整段表格DOM,把表格行的key换成每条招聘数据自带的唯一id即可 - 检查拉取jobInfo的useEffect的依赖数组,确保它不会把
pageInfo、临时计算的变量这类不稳定的值放到依赖里,避免无意义的重复请求 - 计算分页数据的逻辑可以放到
useMemo里缓存,避免每次渲染都重新计算分页切片
内容的提问来源于stack exchange,提问作者bonlim
相关产品推荐
相关产品推荐

