コンポーネント単位のレンダリング
処理の枠組みがわからないので難しい。じゃあコアの部分だけ取り出せばいいじゃん
- コンポーネントを実行する
- 実行結果に差分があればflagを立てる
- flagごとに挿入・削除を行う
関数コンポーネント without hooks
code:js
const Greeting = () => {
return (
<p>Hello, JSConf.jp!</p>
)
}
code:js
const children = Component(props); // <p>Hello, JSConf.jp!</p>
reconcileChildren(current, workInProgress, children);
const flags = workInProgress.flags
if (flags & ChildDeletion) {
}
code:js
function updateFunctionComponent() {
const nextChildren = renderWithHooks(
current,
workInProgress,
Component,
nextProps,
context,
renderLanes,
);
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
return workInProgress.child;
}
コンポーネントの実行
code:js
return children = Component(props, secondArg);
React Elementが生成される
code:js
const element = {
// This tag allows us to uniquely identify this as a React Element
$$typeof: REACT_ELEMENT_TYPE,
// Built-in properties that belong on the element
type: "p",
key: null,
ref: null,
props: { children: "Hello, JSConf.jp!" },
// Record the component responsible for creating this element.
};
Reconcile
code:js
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
ここでcloneするか、deleteするか
flagを立てる。
placement
code:js
function placeSingleChild(newFiber: Fiber): Fiber {
// This is simpler for the single child case. We only need to do a
// placement for inserting new children.
if (shouldTrackSideEffects && newFiber.alternate === null) {
newFiber.flags |= Placement | PlacementDEV;
}
return newFiber;
}
deletion
code:js
function deleteChild(returnFiber: Fiber, childToDelete: Fiber): void {
const deletions = returnFiber.deletions;
if (deletions === null) {
returnFiber.flags |= ChildDeletion;
} else {
deletions.push(childToDelete);
}
}
ここら辺がスライド一枚に落とせないな
flagをみて削除
code:js
function recursivelyTraversePassiveUnmountEffects(parentFiber: Fiber): void {
// Deletions effects can be scheduled on any fiber type. They need to happen
// before the children effects have fired.
const deletions = parentFiber.deletions;
if ((parentFiber.flags & ChildDeletion) !== NoFlags) {
if (deletions !== null) {
for (let i = 0; i < deletions.length; i++) {
const childToDelete = deletionsi; // TODO: Convert this to use recursion
nextEffect = childToDelete;
commitPassiveUnmountEffectsInsideOfDeletedTree_begin(
childToDelete,
parentFiber,
);
}
}
detachAlternateSiblings(parentFiber);
}
const prevDebugFiber = getCurrentDebugFiberInDEV();
// TODO: Split PassiveMask into separate masks for mount and unmount?
if (parentFiber.subtreeFlags & PassiveMask) {
let child = parentFiber.child;
while (child !== null) {
setCurrentDebugFiberInDEV(child);
commitPassiveUnmountOnFiber(child);
child = child.sibling;
}
}
setCurrentDebugFiberInDEV(prevDebugFiber);
}