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