如何避免在useEffect中调用修改状态的函数时出现无限循环
React useEffect无限循环问题修复方案
问题根因
- 组件顶层定义的
func没有做引用缓存,每次组件渲染都会生成新的函数实例,而useEffect依赖了func,实例变化就会触发useEffect执行 useEffect同时依赖了状态arr,但func内部调用setArr修改arr的值,arr更新后又会触发useEffect重新执行,形成死循环
修复方案
1. 移除无效依赖
不需要把当前arr作为参数传入func,也不要把arr加入useEffect依赖项。如果需要基于旧arr计算新值,使用setArr的函数式更新语法即可,该语法可以直接拿到上一次的arr状态,不需要额外声明依赖。
2. 缓存函数引用
用useCallback包裹func,保证只有指定依赖变化时才更新func的引用,避免无意义的useEffect触发。
修复后示例代码
import { useCallback, useEffect, useState } from 'react' // 组件内部逻辑 const [arr, setArr] = useState<any[]>([]) // 用useCallback缓存func,仅内部依赖变化时才更新引用 const func = useCallback((val: any) => { // 你的原有业务逻辑 setArr(prevArr => { // 基于旧arr和val计算新数组,替换成你的实际逻辑 const newArr = [...prevArr, ...val] return newArr }) }, []) // 此处仅添加func内部用到的外部变量作为依赖 useEffect(() => { val?.length > 0 && func(val) }, [val, func])
最简优化方案
如果func仅在当前useEffect中调用,可以直接把逻辑写到useEffect内部,省去函数缓存的步骤:
useEffect(() => { if (!val?.length) return // 直接写原有func的业务逻辑 setArr(prevArr => { // 计算新数组逻辑 return newArr }) }, [val]) // 仅保留val作为依赖,完全避免循环
内容的提问来源于stack exchange,提问作者Erikm
相关产品推荐
相关产品推荐

