React异步更新状态后子组件未重新渲染问题排查
React状态更新后组件未重渲染的问题修复
核心问题所在
你当前的写法有两个致命问题导致组件不重渲染:
- 直接修改原数组引用:用
stateArr.push(res)修改原状态数组,React依赖状态的引用变化判断是否需要重渲染,原数组引用没改,所以setState后React认为状态没更新。 - 异步请求顺序错误:三个
fetch都是异步操作,你在请求还没返回数据时就调用了setState(stateArr),此时数组是空的;后续请求完成后修改数组也不会触发重渲染,因为引用还是原来的。
具体修复方案
方案一:用Promise.all批量处理请求(推荐)
等待所有请求完成后,基于原状态创建新数组更新状态,既保证数据完整性,又符合React状态更新规则:
useEffect(() => { Promise.all([ fetch("https://catfact.ninja/fact").then(res => res.json()), fetch("https://catfact.ninja/fact").then(res => res.json()), fetch("https://catfact.ninja/fact").then(res => res.json()) ]).then(results => { // 函数式更新,确保拿到最新状态 setState(prev => [...prev, ...results]); }); }, []);
方案二:逐个处理请求时的正确写法
如果需要单独处理每个请求的结果,要基于当前状态创建新数组,绝对不能直接修改原数组:
fetch("https://catfact.ninja/fact") .then(res => res.json()) .then(res => { // 用展开运算符创建新数组,传递给setState setState(prevState => [...prevState, res]); });
About组件的优化点
你组件里的rerender状态完全多余,只要父组件状态正确更新,子组件会自动重渲染。另外key={e.length}容易冲突,建议改成更唯一的标识:
const About = ({ arrayProp }) => { return ( <> {arrayProp.map((e, idx) => ( <div key={`fact-${e.length}-${idx}`}> <h6>Break</h6> {e.fact} </div> ))} </> ); };
为什么手动触发重渲染有效?
你加的按钮通过修改rerender让父组件重渲染,此时父组件会重新传递state给子组件——哪怕state引用没变化,父组件重渲染也会带动子组件更新,所以能看到数据,但这是临时 workaround,正确的状态更新才是解决根本问题的方法。
内容的提问来源于stack exchange,提问作者OMGItsRob
相关产品推荐
相关产品推荐

