React useEffect无限循环问题:参数默认值为数组时如何处理?
问题根因
你遇到的无限循环本质是参数解构的默认值每次渲染都会生成新的引用,触发链路是:
- 父组件没有给
Description传list属性,每次组件渲染时都会重新生成一个空数组[]作为默认值,新旧数组引用地址不同 useEffect依赖list,引用变化就会触发回调执行- 回调里调用
setDict更新组件状态,触发组件再次渲染,回到第一步形成循环
去掉默认值时,未传参的list是undefined(基础类型值稳定),去掉setDict时不会触发重渲染,所以两种操作都能打断循环。
可行解决方案
方案1:将默认数组定义为组件外的常量
最适合默认值是固定空数组的场景,常量只会初始化一次,引用永远稳定:
// 组件外部定义常量 const DEFAULT_EMPTY_LIST = [] function Description({list = DEFAULT_EMPTY_LIST}){ const [dict, setDict] = useState({}) useEffect(() => { console.log('只会在list真的变化时触发') setDict({}) }, [list]) return <div>something...</div> }
方案2:用defaultProps声明默认值
React组件的defaultProps定义的默认值只会初始化一次,引用稳定:
function Description({list}){ const [dict, setDict] = useState({}) useEffect(() => { console.log('只会在list真的变化时触发') setDict({}) }, [list]) return <div>something...</div> } // 声明默认属性 Description.defaultProps = { list: [] }
方案3:用useMemo缓存默认值
适合默认值需要动态计算的场景,仅在传入的list变化时才会重新计算值:
function Description({list}){ const [dict, setDict] = useState({}) // 缓存最终使用的list,未传值时返回固定引用的空数组 const finalList = useMemo(() => list ?? [], [list]) useEffect(() => { console.log('只会在list真的变化时触发') setDict({}) }, [finalList]) return <div>something...</div> }
内容的提问来源于stack exchange,提问作者Braven
相关产品推荐
相关产品推荐

