React Fiber 提交宿主副作用
专门供 ReactFiberCommitWork 使用的方法集。
一、作用
二、提交宿主环境挂载
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现commitMount()由宿主环境提供captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitHostMount(finishedWork: Fiber) {
const type = finishedWork.type;
const props = finishedWork.memoizedProps;
const instance: Instance = finishedWork.stateNode;
try {
if (__DEV__) {
runWithFiberInDEV(
finishedWork,
commitMount,
instance,
type,
props,
finishedWork,
);
} else {
commitMount(instance, type, props, finishedWork);
}
} catch (error) {
captureCommitPhaseError(finishedWork, finishedWork.return, error);
}
}
三、提交已水合的宿主实例
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现commitHydratedInstance()由宿主环境提供captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitHostHydratedInstance(finishedWork: Fiber) {
const type = finishedWork.type;
const props = finishedWork.memoizedProps;
const instance: Instance = finishedWork.stateNode;
try {
if (__DEV__) {
runWithFiberInDEV(
finishedWork,
commitHydratedInstance,
instance,
type,
props,
finishedWork,
);
} else {
commitHydratedInstance(instance, type, props, finishedWork);
}
} catch (error) {
captureCommitPhaseError(finishedWork, finishedWork.return, error);
}
}
四、提交宿主环境更新
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现commitUpdate()由宿主环境提供captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitHostUpdate(
finishedWork: Fiber,
newProps: any,
oldProps: any,
): void {
try {
if (__DEV__) {
runWithFiberInDEV(
finishedWork,
commitUpdate,
finishedWork.stateNode,
finishedWork.type,
oldProps,
newProps,
finishedWork,
);
} else {
commitUpdate(
finishedWork.stateNode,
finishedWork.type,
oldProps,
newProps,
finishedWork,
);
}
// Mutations are tracked manually from within commitUpdate.
// 变更是通过 commitUpdate 手动跟踪的。
} catch (error) {
captureCommitPhaseError(finishedWork, finishedWork.return, error);
}
}
五、提交宿主环境文本更新
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现commitTextUpdate()由宿主环境提供trackHostMutation()由 ReactFiberMutationTracking#trackHostMutation 实现captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitHostTextUpdate(
finishedWork: Fiber,
newText: string,
oldText: string,
) {
const textInstance: TextInstance = finishedWork.stateNode;
try {
if (__DEV__) {
runWithFiberInDEV(
finishedWork,
commitTextUpdate,
textInstance,
oldText,
newText,
);
} else {
commitTextUpdate(textInstance, oldText, newText);
}
trackHostMutation();
} catch (error) {
captureCommitPhaseError(finishedWork, finishedWork.return, error);
}
}
六、提交宿主环境重置文本内容
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现resetTextContent()由宿主环境提供trackHostMutation()由 ReactFiberMutationTracking#trackHostMutation 实现captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitHostResetTextContent(finishedWork: Fiber) {
const instance: Instance = finishedWork.stateNode;
try {
if (__DEV__) {
runWithFiberInDEV(finishedWork, resetTextContent, instance);
} else {
resetTextContent(instance);
}
trackHostMutation();
} catch (error) {
captureCommitPhaseError(finishedWork, finishedWork.return, error);
}
}
七、提交显示隐藏挂起边界
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现hideDehydratedBoundary()由宿主环境提供unhideDehydratedBoundary()由宿主环境提供captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitShowHideSuspenseBoundary(node: Fiber, isHidden: boolean) {
try {
const instance = node.stateNode;
if (isHidden) {
if (__DEV__) {
runWithFiberInDEV(node, hideDehydratedBoundary, instance);
} else {
hideDehydratedBoundary(instance);
}
} else {
if (__DEV__) {
runWithFiberInDEV(node, unhideDehydratedBoundary, node.stateNode);
} else {
unhideDehydratedBoundary(node.stateNode);
}
}
} catch (error) {
captureCommitPhaseError(node, node.return, error);
}
}
八、提交显示/隐藏宿主环境实例
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现hideInstance()由宿主环境提供unhideInstance()由宿主环境提供captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitShowHideHostInstance(node: Fiber, isHidden: boolean) {
try {
const instance = node.stateNode;
if (isHidden) {
if (__DEV__) {
runWithFiberInDEV(node, hideInstance, instance);
} else {
hideInstance(instance);
}
} else {
if (__DEV__) {
runWithFiberInDEV(
node,
unhideInstance,
node.stateNode,
node.memoizedProps,
);
} else {
unhideInstance(node.stateNode, node.memoizedProps);
}
}
} catch (error) {
captureCommitPhaseError(node, node.return, error);
}
}
九、提交显示隐藏宿主环境文本实例
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现hideTextInstance()由宿主环境提供unhideTextInstance()由宿主环境提供trackHostMutation()由 ReactFiberMutationTracking#trackHostMutation 提供captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitShowHideHostTextInstance(node: Fiber, isHidden: boolean) {
try {
const instance = node.stateNode;
if (isHidden) {
if (__DEV__) {
runWithFiberInDEV(node, hideTextInstance, instance);
} else {
hideTextInstance(instance);
}
} else {
if (__DEV__) {
runWithFiberInDEV(
node,
unhideTextInstance,
instance,
node.memoizedProps,
);
} else {
unhideTextInstance(instance, node.memoizedProps);
}
}
trackHostMutation();
} catch (error) {
captureCommitPhaseError(node, node.return, error);
}
}
十、将新子项提交到片段实例
export function commitNewChildToFragmentInstances(
fiber: Fiber,
parentFragmentInstances: null | Array<FragmentInstanceType>,
): void {
if (
fiber.tag !== HostComponent ||
// Only run fragment insertion effects for initial insertions
// 仅对初始插入运行片段插入效果
fiber.alternate !== null ||
parentFragmentInstances === null
) {
return;
}
for (let i = 0; i < parentFragmentInstances.length; i++) {
const fragmentInstance = parentFragmentInstances[i];
commitNewChildToFragmentInstance(fiber.stateNode, fragmentInstance);
}
}
十一、提交片段实例插入效果
备注
commitNewChildToFragmentInstance()由宿主环境提供
export function commitFragmentInstanceInsertionEffects(fiber: Fiber): void {
let parent = fiber.return;
while (parent !== null) {
if (isFragmentInstanceParent(parent)) {
const fragmentInstance: FragmentInstanceType = parent.stateNode;
commitNewChildToFragmentInstance(fiber.stateNode, fragmentInstance);
}
if (isHostParent(parent)) {
return;
}
parent = parent.return;
}
}
十二、提交片段实例删除效果
备注
deleteChildFromFragmentInstance()由宿主环境提供
export function commitFragmentInstanceDeletionEffects(fiber: Fiber): void {
let parent = fiber.return;
while (parent !== null) {
if (isFragmentInstanceParent(parent)) {
const fragmentInstance: FragmentInstanceType = parent.stateNode;
deleteChildFromFragmentInstance(fiber.stateNode, fragmentInstance);
}
if (isHostParent(parent)) {
return;
}
parent = parent.return;
}
}
十三、提交宿主环境放置
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitHostPlacement(finishedWork: Fiber) {
try {
if (__DEV__) {
runWithFiberInDEV(finishedWork, commitPlacement, finishedWork);
} else {
commitPlacement(finishedWork);
}
} catch (error) {
captureCommitPhaseError(finishedWork, finishedWork.return, error);
}
}
十四、提交宿主环境从容器中移除子项
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现removeChildFromContainer()由宿主环境提供trackHostMutation()由 ReactFiberMutationTracking#trackHostMutation 提供captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitHostRemoveChildFromContainer(
deletedFiber: Fiber,
nearestMountedAncestor: Fiber,
parentContainer: Container,
hostInstance: Instance | TextInstance,
) {
try {
if (__DEV__) {
runWithFiberInDEV(
deletedFiber,
removeChildFromContainer,
parentContainer,
hostInstance,
);
} else {
removeChildFromContainer(parentContainer, hostInstance);
}
trackHostMutation();
} catch (error) {
captureCommitPhaseError(deletedFiber, nearestMountedAncestor, error);
}
}
十五、提交宿主环境移除子项
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现removeChild()由宿主环境提供trackHostMutation()由 ReactFiberMutationTracking#trackHostMutation 提供captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitHostRemoveChild(
deletedFiber: Fiber,
nearestMountedAncestor: Fiber,
parentInstance: Instance,
hostInstance: Instance | TextInstance,
) {
try {
if (__DEV__) {
runWithFiberInDEV(
deletedFiber,
removeChild,
parentInstance,
hostInstance,
);
} else {
removeChild(parentInstance, hostInstance);
}
trackHostMutation();
} catch (error) {
captureCommitPhaseError(deletedFiber, nearestMountedAncestor, error);
}
}
十六、提交宿主环境根容器子节点
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现replaceContainerChildren()由宿主环境提供trackHostMutation()由 ReactFiberMutationTracking#trackHostMutation 提供captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitHostRootContainerChildren(
root: FiberRoot,
finishedWork: Fiber,
) {
const containerInfo = root.containerInfo;
const pendingChildren = root.pendingChildren;
try {
if (__DEV__) {
runWithFiberInDEV(
finishedWork,
replaceContainerChildren,
containerInfo,
pendingChildren,
);
} else {
replaceContainerChildren(containerInfo, pendingChildren);
}
trackHostMutation();
} catch (error) {
captureCommitPhaseError(finishedWork, finishedWork.return, error);
}
}
十七、提交宿主环境门户容器子项
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现replaceContainerChildren()由宿主环境提供captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitHostPortalContainerChildren(
portal: {
containerInfo: Container;
pendingChildren: ChildSet;
// - ...
},
finishedWork: Fiber,
pendingChildren: ChildSet,
) {
const containerInfo = portal.containerInfo;
try {
if (__DEV__) {
runWithFiberInDEV(
finishedWork,
replaceContainerChildren,
containerInfo,
pendingChildren,
);
} else {
replaceContainerChildren(containerInfo, pendingChildren);
}
} catch (error) {
captureCommitPhaseError(finishedWork, finishedWork.return, error);
}
}
十八、提交已水合的宿主容器
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现commitHydratedContainer()由宿主环境提供captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitHostHydratedContainer(
root: FiberRoot,
finishedWork: Fiber,
) {
try {
if (__DEV__) {
runWithFiberInDEV(
finishedWork,
commitHydratedContainer,
root.containerInfo,
);
} else {
commitHydratedContainer(root.containerInfo);
}
} catch (error) {
captureCommitPhaseError(finishedWork, finishedWork.return, error);
}
}
十九、提交宿主环境已加载活动
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现commitHydratedActivityInstance()由宿主环境提供captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitHostHydratedActivity(
activityInstance: ActivityInstance,
finishedWork: Fiber,
) {
try {
if (__DEV__) {
runWithFiberInDEV(
finishedWork,
commitHydratedActivityInstance,
activityInstance,
);
} else {
commitHydratedActivityInstance(activityInstance);
}
} catch (error) {
captureCommitPhaseError(finishedWork, finishedWork.return, error);
}
}
二十、提交已加载的宿主挂起
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现commitHydratedSuspenseInstance()由宿主环境提供captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitHostHydratedSuspense(
suspenseInstance: SuspenseInstance,
finishedWork: Fiber,
) {
try {
if (__DEV__) {
runWithFiberInDEV(
finishedWork,
commitHydratedSuspenseInstance,
suspenseInstance,
);
} else {
commitHydratedSuspenseInstance(suspenseInstance);
}
} catch (error) {
captureCommitPhaseError(finishedWork, finishedWork.return, error);
}
}
廿一、提交宿主环境单例获取
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现acquireSingletonInstance()由宿主环境提供captureCommitPhaseError()由 ReactFiberWorkLoop 提供
export function commitHostSingletonAcquisition(finishedWork: Fiber) {
const singleton = finishedWork.stateNode;
const props = finishedWork.memoizedProps;
try {
// This was a new mount, acquire the DOM instance and set initial properties
// 这是一个新的挂载,获取 DOM 实例并设置初始属性
if (__DEV__) {
runWithFiberInDEV(
finishedWork,
acquireSingletonInstance,
finishedWork.type,
props,
singleton,
finishedWork,
);
} else {
acquireSingletonInstance(
finishedWork.type,
props,
singleton,
finishedWork,
);
}
} catch (error) {
captureCommitPhaseError(finishedWork, finishedWork.return, error);
}
}
二十二、提交宿主环境单例释放
备注
runWithFiberInDEV()由 ReactCurrentFiber#runWithFiberInDEV 实现releaseSingletonInstance()由宿主环境提供
export function commitHostSingletonRelease(releasingWork: Fiber) {
if (__DEV__) {
runWithFiberInDEV(
releasingWork,
releaseSingletonInstance,
releasingWork.stateNode,
);
} else {
releaseSingletonInstance(releasingWork.stateNode);
}
}
廿三、工具
1. 是否为宿主环境父级
备注
isSingletonScope()由宿主环境提供
function isHostParent(fiber: Fiber): boolean {
return (
fiber.tag === HostComponent ||
fiber.tag === HostRoot ||
(supportsResources ? fiber.tag === HostHoistable : false) ||
(supportsSingletons
? fiber.tag === HostSingleton && isSingletonScope(fiber.type)
: false) ||
fiber.tag === HostPortal
);
}
2. 是片段实例父类
function isFragmentInstanceParent(fiber: Fiber): boolean {
return fiber && fiber.tag === Fragment && fiber.stateNode !== null;
}
3. 获取宿主环境兄弟节点
备注
isSingletonScope()由宿主环境提供
function getHostSibling(fiber: Fiber): ?Instance {
// We're going to search forward into the tree until we find a sibling host
// node. Unfortunately, if multiple insertions are done in a row we have to
// search past them. This leads to exponential search for the next sibling.
// TODO: Find a more efficient way to do this.
//
// 我们将向前在树中搜索,直到找到一个兄弟宿主节点。
// 不幸的是,如果连续进行了多个插入,我们必须跳过它们进行搜索。
// 这会导致寻找下一个兄弟节点的搜索呈指数增长。
// TODO:找到一种更高效的方法来实现这一点。
let node: Fiber = fiber;
siblings: while (true) {
// If we didn't find anything, let's try the next sibling.
// 如果我们什么都没找到,那就尝试下一个兄弟节点。
while (node.sibling === null) {
if (node.return === null || isHostParent(node.return)) {
// If we pop out of the root or hit the parent the fiber we are the
// last sibling.
//
// 如果我们从根节点弹出或到达父节点,说明我们是最后一个兄弟节点。
return null;
}
node = node.return;
}
node.sibling.return = node.return;
node = node.sibling;
while (
node.tag !== HostComponent &&
node.tag !== HostText &&
node.tag !== DehydratedFragment
) {
// If this is a host singleton we go deeper if it's not a special
// singleton scope. If it is a singleton scope we skip over it because
// you only insert against this scope when you are already inside of it
//
// 如果这是一个宿主环境单例,我们会深入,如果它不是一个特殊的单例范围。如果它是单例范围,我
// 们会跳过它,因为你只有在已经处于该范围内时才会对其进行插入
if (
supportsSingletons &&
node.tag === HostSingleton &&
isSingletonScope(node.type)
) {
continue siblings;
}
// If it is not host node and, we might have a host node inside it.
// Try to search down until we find one.
//
// 如果它不是宿主环境节点,我们可能在它里面有一个宿主环境节点。
// 尝试向下搜索,直到找到一个。
if (node.flags & Placement) {
// If we don't have a child, try the siblings instead.
// 如果我们没有子节点,则尝试使用兄弟节点。
continue siblings;
}
// If we don't have a child, try the siblings instead.
// We also skip portals because they are not part of this host tree.
//
// 如果我们没有子节点,则尝试使用兄弟节点。
// 我们也会跳过门户,因为它们不是此宿主环境树的一部分。
if (node.child === null || node.tag === HostPortal) {
continue siblings;
} else {
node.child.return = node;
node = node.child;
}
}
// Check if this host node is stable or about to be placed.
// 检查这个宿主环境节点是否稳定或即将被放置。
if (!(node.flags & Placement)) {
// Found it!
// 找到了!
return node.stateNode;
}
}
}
4. 将 Placement 节点插入或追加到容器中
备注
insertInContainerBefore()由宿主环境提供appendChildToContainer()由宿主环境提供trackHostMutation()由 ReactFiberMutationTracking#trackHostMutation 实现isSingletonScope()由宿主环境提供
function insertOrAppendPlacementNodeIntoContainer(
node: Fiber,
before: ?Instance,
parent: Container,
parentFragmentInstances: null | Array<FragmentInstanceType>,
): void {
const { tag } = node;
const isHost = tag === HostComponent || tag === HostText;
if (isHost) {
const stateNode = node.stateNode;
if (before) {
insertInContainerBefore(parent, stateNode, before);
} else {
appendChildToContainer(parent, stateNode);
}
if (enableFragmentRefs) {
commitNewChildToFragmentInstances(node, parentFragmentInstances);
}
trackHostMutation();
return;
} else if (tag === HostPortal) {
// If the insertion itself is a portal, then we don't want to traverse
// down its children. Instead, we'll get insertions from each child in
// the portal directly.
//
// 如果插入本身是一个门户,那么我们不想遍历它的子节点。相反,我们将直接从门户中的每个
// 子节点获取插入内容。
return;
}
if (
(supportsSingletons ? tag === HostSingleton : false) &&
isSingletonScope(node.type)
) {
// This singleton is the parent of deeper nodes and needs to become
// the parent for child insertions and appends
//
// 这个单例是更深层节点的父节点,需要成为子节点插入和追加的父节点
parent = node.stateNode;
before = null;
}
const child = node.child;
if (child !== null) {
insertOrAppendPlacementNodeIntoContainer(
child,
before,
parent,
parentFragmentInstances,
);
let sibling = child.sibling;
while (sibling !== null) {
insertOrAppendPlacementNodeIntoContainer(
sibling,
before,
parent,
parentFragmentInstances,
);
sibling = sibling.sibling;
}
}
}
5. 插入或附加放置节点
备注
insertBefore()由宿主环境提供appendChild()由宿主环境提供trackHostMutation()由 ReactFiberMutationTracking#trackHostMutation 提供isSingletonScope()由宿主环境提供
function insertOrAppendPlacementNode(
node: Fiber,
before: ?Instance,
parent: Instance,
parentFragmentInstances: null | Array<FragmentInstanceType>,
): void {
const { tag } = node;
const isHost = tag === HostComponent || tag === HostText;
if (isHost) {
const stateNode = node.stateNode;
if (before) {
insertBefore(parent, stateNode, before);
} else {
appendChild(parent, stateNode);
}
if (enableFragmentRefs) {
commitNewChildToFragmentInstances(node, parentFragmentInstances);
}
trackHostMutation();
return;
} else if (tag === HostPortal) {
// If the insertion itself is a portal, then we don't want to traverse
// down its children. Instead, we'll get insertions from each child in
// the portal directly.
//
// 如果插入本身是一个门户,那么我们不想遍历它的子节点。相反,我们将直接从门户中的每
// 个子节点获取插入内容。
return;
}
if (
(supportsSingletons ? tag === HostSingleton : false) &&
isSingletonScope(node.type)
) {
// This singleton is the parent of deeper nodes and needs to become
// the parent for child insertions and appends
//
// 这个单例是更深层节点的父节点,需要成为子节点插入和追加的父节点
parent = node.stateNode;
}
const child = node.child;
if (child !== null) {
insertOrAppendPlacementNode(child, before, parent, parentFragmentInstances);
let sibling = child.sibling;
while (sibling !== null) {
insertOrAppendPlacementNode(
sibling,
before,
parent,
parentFragmentInstances,
);
sibling = sibling.sibling;
}
}
}
6. 提交位置
备注
resetTextContent()由宿主环境提供
function commitPlacement(finishedWork: Fiber): void {
// Recursively insert all host nodes into the parent.
// 递归地将所有宿主环境节点插入到父节点中。
let hostParentFiber;
let parentFragmentInstances = null;
let parentFiber = finishedWork.return;
while (parentFiber !== null) {
if (enableFragmentRefs && isFragmentInstanceParent(parentFiber)) {
const fragmentInstance: FragmentInstanceType = parentFiber.stateNode;
if (parentFragmentInstances === null) {
parentFragmentInstances = [fragmentInstance];
} else {
parentFragmentInstances.push(fragmentInstance);
}
}
if (isHostParent(parentFiber)) {
hostParentFiber = parentFiber;
break;
}
parentFiber = parentFiber.return;
}
if (!supportsMutation) {
if (enableFragmentRefs) {
commitImmutablePlacementNodeToFragmentInstances(
finishedWork,
parentFragmentInstances,
);
}
return;
}
if (hostParentFiber == null) {
throw new Error(
'Expected to find a host parent. This error is likely caused by a bug ' +
'in React. Please file an issue.',
);
}
switch (hostParentFiber.tag) {
case HostSingleton: {
if (supportsSingletons) {
const parent: Instance = hostParentFiber.stateNode;
const before = getHostSibling(finishedWork);
// We only have the top Fiber that was inserted but we need to recurse down its
// children to find all the terminal nodes.
//
// 我们只有被插入的顶层 Fiber,但我们需要递归它的子节点来找到所有终端节点。
insertOrAppendPlacementNode(
finishedWork,
before,
parent,
parentFragmentInstances,
);
break;
}
// Fall through
// 贯穿
}
case HostComponent: {
const parent: Instance = hostParentFiber.stateNode;
if (hostParentFiber.flags & ContentReset) {
// Reset the text content of the parent before doing any insertions
// 在进行任何插入之前重置父元素的文本内容
resetTextContent(parent);
// Clear ContentReset from the effect tag
// 从效果标签中清除内容重置
hostParentFiber.flags &= ~ContentReset;
}
const before = getHostSibling(finishedWork);
// We only have the top Fiber that was inserted but we need to recurse down its
// children to find all the terminal nodes.
//
// 我们只有被插入的顶层 Fiber,但我们需要递归它的子节点来找到所有终端节点。
insertOrAppendPlacementNode(
finishedWork,
before,
parent,
parentFragmentInstances,
);
break;
}
case HostRoot:
case HostPortal: {
const parent: Container = hostParentFiber.stateNode.containerInfo;
const before = getHostSibling(finishedWork);
insertOrAppendPlacementNodeIntoContainer(
finishedWork,
before,
parent,
parentFragmentInstances,
);
break;
}
default:
throw new Error(
'Invalid host parent fiber. This error is likely caused by a bug ' +
'in React. Please file an issue.',
);
}
}
7. 将不可变放置节点提交到片段实例
function commitImmutablePlacementNodeToFragmentInstances(
finishedWork: Fiber,
parentFragmentInstances: null | Array<FragmentInstanceType>,
): void {
if (!enableFragmentRefs) {
return;
}
const isHost = finishedWork.tag === HostComponent;
if (isHost) {
commitNewChildToFragmentInstances(finishedWork, parentFragmentInstances);
return;
} else if (finishedWork.tag === HostPortal) {
// If the insertion itself is a portal, then we don't want to traverse
// down its children. Instead, we'll get insertions from each child in
// the portal directly.
//
// 如果插入本身是一个门户,那么我们不想遍历它的子节点。相反,我们将直接从门户中的每
// 个子节点获取插入内容。
return;
}
const child = finishedWork.child;
if (child !== null) {
commitImmutablePlacementNodeToFragmentInstances(
child,
parentFragmentInstances,
);
let sibling = child.sibling;
while (sibling !== null) {
commitImmutablePlacementNodeToFragmentInstances(
sibling,
parentFragmentInstances,
);
sibling = sibling.sibling;
}
}
}