You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React父子组件useEffect执行顺序不符预期的原因咨询

React useEffect执行顺序差异原因解析

问题描述

在父组件输入框中输入内容触发组件更新时,我预期的useEffect执行顺序为:

  1. end child(子组件清理函数)
  2. child(子组件effect函数)
  3. end parent(父组件清理函数)
  4. parent(父组件effect函数)

但实际执行结果却是:

  1. end child(子组件清理函数)
  2. end parent(父组件清理函数)
  3. child(子组件effect函数)
  4. parent(父组件effect函数)

请问产生这种差异的原因是什么?

复现代码

function App() {
  return (
    <div className="App">
      <Container/>
      <Parent/>
    </div>
  );
}

function Parent(){
  const [first, setFirst] = useState('');
  const [second, setSecond] = useState('');

  function final(e){
    setSecond(e.target.value);
  }

  function func(e){
    setFirst(e.target.value);
  }

  useEffect(()=>{
    console.log('parent'); // 预期第4步,实际第4步
    return ()=>{console.log('end parent')} // 预期第3步,实际第2步
  },[first, second])

  return (
    <>
      <h1>I am parent</h1>
      <input style={{border:"1px solid black"}} value={first} onChange={(e)=>{func(e)}}/>
      <input style={{border:"1px solid black"}} value={second} onChange={(e)=>{final(e)}}/>
      {
        first.length < 7 ? <TestEffect fistArgument={first} secondArgument={second}/> : <h1>lorem ipsum dolor</h1>
      }
    </>
  )
}

function TestEffect({fistArgument, secondArgument}){
  const [extra, setExtra] = useState(0);
  const [force, setForce] = useState(0);
    
  useEffect(()=>{
    console.log('child'); // 预期第2步,实际第3步
    return ()=>{console.log('end child')} // 预期第1步,实际第1步
  },[extra, force, fistArgument, secondArgument])

  return (
    <>
      <h1 onClick={()=>{setExtra(extra+1)}}>{fistArgument}</h1>
      <h1 onClick={()=>{setForce(force+1)}}>{secondArgument}</h1>
    </>
  )
}

export default App;

原因分析

这种差异完全由React的副作用执行机制决定,核心点在于一次更新周期内,React会先批量执行所有需要触发的清理函数,再批量执行所有新的effect函数:

  1. 清理函数的执行逻辑:当组件的依赖项变化(或组件即将卸载)时,React会先按子组件→父组件的顺序执行所有待触发的清理函数。在你的场景中,父组件的first状态变化后,子组件的props和父组件的effect依赖项都发生了改变,两者的旧effect都需要清理,因此会先执行子组件的end child,再执行父组件的end parent。

  2. effect函数的执行逻辑:所有清理操作完成后,React会按子组件→父组件的顺序执行新的effect函数,也就是先执行子组件的child,再执行父组件的parent。

你的预期错误在于,误以为子组件的清理和新effect会成对执行(清理完子组件立刻执行其新effect),再处理父组件的相关逻辑,但React的批量处理机制是为了性能优化,确保同一更新周期内的副作用操作集中完成,避免零散执行带来的性能损耗和逻辑混乱。

内容的提问来源于stack exchange,提问作者hossein olfat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 13:14:56