【React源码学习】5 EffectList的构建过程


demo

export default function App() {
    const [toggle, setToggle] = useState(true);
    const a = <div key="a">a</div>;
    const b = <div key="b">b</div>;

    return (
        <div
            onClick={() => {
                setToggle(!toggle);
            }}
        >
            {toggle ? a : b}
        </div>
    );
}

efectList的构建

触发更新后直接看key=a的处理过程

function deleteChild(returnFiber, childToDelete) {
  if (!shouldTrackSideEffects) {
    return;
  } 
  var last = returnFiber.lastEffect;

  if (last !== null) {
      last.nextEffect = childToDelete;
      returnFiber.lastEffect = childToDelete;
  } else {
      returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
  }

  childToDelete.nextEffect = null;
  childToDelete.flags = Deletion;
}

returnFiber时workInProgress的父fiber,childToDelete是正在diff的current fiber,由于key不相同,打上Deletion的同时设置了effect list

if (last !== null) {
    last.nextEffect = childToDelete;
    returnFiber.lastEffect = childToDelete;
} else {
    returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
}

子节点要发生变化(Deletion)时,将子fiber添加到父fiber的effect list上,可以说effect list保存的是将要改变的子fiber

effectList的连接

if (completedWork.lastEffect !== null) {
    if (returnFiber.lastEffect !== null) {
        returnFiber.lastEffect.nextEffect = completedWork.firstEffect;
    }
    returnFiber.lastEffect = completedWork.lastEffect;
}

if (flags > PerformedWork) {
    if (returnFiber.lastEffect !== null) {
        returnFiber.lastEffect.nextEffect = completedWork;
    } else {
        returnFiber.firstEffect = completedWork;
    }
    returnFiber.lastEffect = completedWork;
}

在向上调用completeWork时,会将beginWork中构建的effectList传递给父fiber的lastEffect(returnFiber.lastEffect.nextEffect = completeWork.lastEffect),这样就完成了链表的连接。在root上可以拿到完整的effectList

summary

demo完整的effectList


Author: Maple
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Maple !
  TOC