React初始渲染时子组件useEffect未更新父组件state,点击按钮可更新如何解决
问题根因
- 父组件初始赋值时机错误:你将初始的10个表单ref的赋值逻辑放在了空依赖的
useEffect中,这个钩子的执行时机晚于所有子组件的挂载后useEffect。也就是说初始渲染时,子组件CreateItem先把自己的ref添加到了refsArr,随后父组件的useEffect执行,直接将refsArr覆盖为你定义的10个ref数组,子组件的添加操作直接被覆盖失效。 - 子组件更新state存在闭包陷阱:
CreateItem的useEffect依赖项为空,直接基于当前拿到的refsArr快照进行扩展更新,当有多个CreateItem同时初始化时,多个更新操作会互相覆盖,最终只会保留最后一个子组件添加的内容。 - 额外的语法问题:你在子组件更新时额外嵌套了一层数组
[{ itemNameRef, qtyRef, priceRef }],会导致refsArr的结构不一致,后续取值容易出错。
修复方案
- 父组件去掉初始赋值的
useEffect,直接将初始值传入useState,避免后续覆盖子组件的更新:
// 直接作为state初始值,不需要放在useEffect中 const [refsArr, setRefsArr] = useState([ { fromAddress }, { fromCity }, { fromPC }, { fromCountry }, { toCName }, { toAddress }, { toCity }, { toPC }, { toCountry }, { desc }, ]);
- 子组件改用函数式更新
refsArr,基于最新的前序state进行扩展,规避闭包问题,同时去掉多余的数组嵌套:
useEffect(() => { // 函数式更新可以拿到最新的prev state,不会受闭包影响 setRefsArr(prev => [...prev, { itemNameRef, qtyRef, priceRef }]); // 如果有删除item的需求,补充以下清理逻辑,避免无效ref残留 return () => { setRefsArr(prev => prev.filter(ref => ref.itemNameRef !== itemNameRef)); } }, []);
内容的提问来源于stack exchange,提问作者Nikola Golubović
相关产品推荐
相关产品推荐

