;
const pending = updateQueue.shared.pending;
updateQueue.shared.pending = null;
const { memoizedState } = processUpdateQueue(baseState, pending, renderLanes);
From 41e1b4aff567804a872a19674c1a6efcce07abf6 Mon Sep 17 00:00:00 2001
From: kasong <313439271@qq.com>
Date: Thu, 20 Apr 2023 22:52:52 +0800
Subject: [PATCH 11/15] feat: ref
---
demos/ref/index.html | 16 +++
demos/ref/main.tsx | 25 +++++
demos/ref/vite-env.d.ts | 1 +
demos/vite.config.js | 4 +-
package.json | 2 +-
packages/react-reconciler/src/beginWork.ts | 13 +++
packages/react-reconciler/src/commitWork.ts | 104 +++++++++++++-----
packages/react-reconciler/src/completeWork.ts | 15 ++-
packages/react-reconciler/src/fiber.ts | 4 +-
packages/react-reconciler/src/fiberFlags.ts | 4 +-
packages/react-reconciler/src/fiberHooks.ts | 18 ++-
packages/react-reconciler/src/workLoop.ts | 2 +
packages/react/index.ts | 5 +
packages/react/src/currentDispatcher.ts | 1 +
packages/shared/ReactTypes.ts | 2 +-
15 files changed, 181 insertions(+), 35 deletions(-)
create mode 100644 demos/ref/index.html
create mode 100644 demos/ref/main.tsx
create mode 100644 demos/ref/vite-env.d.ts
diff --git a/demos/ref/index.html b/demos/ref/index.html
new file mode 100644
index 0000000..5d0dbe9
--- /dev/null
+++ b/demos/ref/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ noop-renderer测试
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/ref/main.tsx b/demos/ref/main.tsx
new file mode 100644
index 0000000..801c24e
--- /dev/null
+++ b/demos/ref/main.tsx
@@ -0,0 +1,25 @@
+import { useState, useEffect, useRef } from 'react';
+import { createRoot } from 'react-dom/client';
+
+function App() {
+ const [isDel, del] = useState(false);
+ const divRef = useRef(null);
+
+ console.warn('render divRef', divRef.current);
+
+ useEffect(() => {
+ console.warn('useEffect divRef', divRef.current);
+ }, []);
+
+ return (
+ del(true)}>
+ {isDel ? null : }
+
+ );
+}
+
+function Child() {
+ return console.warn('dom is:', dom)}>Child
;
+}
+
+createRoot(document.getElementById('root') as HTMLElement).render();
diff --git a/demos/ref/vite-env.d.ts b/demos/ref/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/demos/ref/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/demos/vite.config.js b/demos/vite.config.js
index 34c4583..8ceff5b 100644
--- a/demos/vite.config.js
+++ b/demos/vite.config.js
@@ -34,8 +34,8 @@ export default defineConfig({
find: 'hostConfig',
replacement: path.resolve(
__dirname,
- '../packages/react-noop-renderer/src/hostConfig.ts'
- // '../packages/react-dom/src/hostConfig.ts'
+ // '../packages/react-noop-renderer/src/hostConfig.ts'
+ '../packages/react-dom/src/hostConfig.ts'
)
}
]
diff --git a/package.json b/package.json
index 937b779..c2c2a1b 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,7 @@
"license": "MIT",
"scripts": {
"build:dev": "rm -rf dist && rollup --config scripts/rollup/dev.config.js",
- "demo": "vite serve demos/noop-renderer --config demos/vite.config.js --force",
+ "demo": "vite serve demos/ref --config demos/vite.config.js --force",
"lint": "eslint --ext .ts,.jsx,.tsx --fix --quiet ./packages",
"test": "jest --config scripts/jest/jest.config.js"
},
diff --git a/packages/react-reconciler/src/beginWork.ts b/packages/react-reconciler/src/beginWork.ts
index 9dc66a8..e8a67d8 100644
--- a/packages/react-reconciler/src/beginWork.ts
+++ b/packages/react-reconciler/src/beginWork.ts
@@ -11,6 +11,7 @@ import {
HostRoot,
HostText
} from './workTags';
+import { Ref } from './fiberFlags';
export const beginWork = (workInProgress: FiberNode, renderLanes: Lanes) => {
if (__LOG__) {
@@ -55,6 +56,7 @@ function updateHostComponent(workInProgress: FiberNode, renderLanes: Lanes) {
// 根据element创建fiberNode
const nextProps = workInProgress.pendingProps;
const nextChildren = nextProps.children;
+ markRef(workInProgress.alternate, workInProgress);
reconcileChildren(workInProgress, nextChildren, renderLanes);
return workInProgress.child;
}
@@ -97,3 +99,14 @@ function reconcileChildren(
);
}
}
+
+function markRef(current: FiberNode | null, workInProgress: FiberNode) {
+ const ref = workInProgress.ref;
+
+ if (
+ (current === null && ref !== null) ||
+ (current !== null && current.ref !== ref)
+ ) {
+ workInProgress.flags |= Ref;
+ }
+}
diff --git a/packages/react-reconciler/src/commitWork.ts b/packages/react-reconciler/src/commitWork.ts
index cbdc492..d7f8cd5 100644
--- a/packages/react-reconciler/src/commitWork.ts
+++ b/packages/react-reconciler/src/commitWork.ts
@@ -2,12 +2,14 @@ import { FiberNode, FiberRootNode, PendingPassiveEffects } from './fiber';
import {
ChildDeletion,
Flags,
+ LayoutMask,
MutationMask,
NoFlags,
PassiveEffect,
PassiveMask,
Placement,
- Update
+ Update,
+ Ref
} from './fiberFlags';
import { Effect, FCUpdateQueue } from './fiberHooks';
import { HookHasEffect } from './hookEffectTags';
@@ -29,42 +31,42 @@ import {
let nextEffect: FiberNode | null = null;
// 以DFS形式执行
-export const commitMutationEffects = (
- finishedWork: FiberNode,
- root: FiberRootNode
+const commitEffects = (
+ phrase: 'mutation' | 'layout',
+ mask: Flags,
+ callback: (fiber: FiberNode, root: FiberRootNode) => void
) => {
- nextEffect = finishedWork;
+ return (finishedWork: FiberNode, root: FiberRootNode) => {
+ nextEffect = finishedWork;
- while (nextEffect !== null) {
- // 向下遍历
- const child: FiberNode | null = nextEffect.child;
+ while (nextEffect !== null) {
+ // 向下遍历
+ const child: FiberNode | null = nextEffect.child;
- if (
- (nextEffect.subtreeFlags & (MutationMask | PassiveMask)) !== NoFlags &&
- child !== null
- ) {
- nextEffect = child;
- } else {
- // 向上遍历
- up: while (nextEffect !== null) {
- commitMutationEffectsOnFiber(nextEffect, root);
- const sibling: FiberNode | null = nextEffect.sibling;
-
- if (sibling !== null) {
- nextEffect = sibling;
- break up;
+ if ((nextEffect.subtreeFlags & mask) !== NoFlags && child !== null) {
+ nextEffect = child;
+ } else {
+ // 向上遍历
+ up: while (nextEffect !== null) {
+ callback(nextEffect, root);
+ const sibling: FiberNode | null = nextEffect.sibling;
+
+ if (sibling !== null) {
+ nextEffect = sibling;
+ break up;
+ }
+ nextEffect = nextEffect.return;
}
- nextEffect = nextEffect.return;
}
}
- }
+ };
};
const commitMutationEffectsOnFiber = (
finishedWork: FiberNode,
root: FiberRootNode
) => {
- const flags = finishedWork.flags;
+ const { flags, tag } = finishedWork;
if ((flags & Placement) !== NoFlags) {
// 插入/移动
@@ -90,8 +92,59 @@ const commitMutationEffectsOnFiber = (
commitPassiveEffect(finishedWork, root, 'update');
finishedWork.flags &= ~PassiveEffect;
}
+ if ((flags & Ref) !== NoFlags && tag === HostComponent) {
+ safelyDetachRef(finishedWork);
+ }
};
+function safelyDetachRef(current: FiberNode) {
+ const ref = current.ref;
+ if (ref !== null) {
+ if (typeof ref === 'function') {
+ ref(null);
+ } else {
+ ref.current = null;
+ }
+ }
+}
+
+const commitLayoutEffectsOnFiber = (
+ finishedWork: FiberNode,
+ root: FiberRootNode
+) => {
+ const { flags, tag } = finishedWork;
+
+ if ((flags & Ref) !== NoFlags && tag === HostComponent) {
+ // 绑定新的ref
+ safelyAttachRef(finishedWork);
+ finishedWork.flags &= ~Ref;
+ }
+};
+
+function safelyAttachRef(fiber: FiberNode) {
+ const ref = fiber.ref;
+ if (ref !== null) {
+ const instance = fiber.stateNode;
+ if (typeof ref === 'function') {
+ ref(instance);
+ } else {
+ ref.current = instance;
+ }
+ }
+}
+
+export const commitMutationEffects = commitEffects(
+ 'mutation',
+ MutationMask | PassiveMask,
+ commitMutationEffectsOnFiber
+);
+
+export const commitLayoutEffects = commitEffects(
+ 'layout',
+ LayoutMask,
+ commitLayoutEffectsOnFiber
+);
+
/**
* 难点在于目标fiber的hostSibling可能并不是他的同级sibling
* 比如: 其中:function B() {return } 所以A的hostSibling实际是B的child
@@ -249,6 +302,7 @@ function commitDeletion(childToDelete: FiberNode, root: FiberRootNode) {
case HostComponent:
recordHostChildrenToDelete(hostChildrenToDelete, unmountFiber);
// 解绑ref
+ safelyDetachRef(unmountFiber);
return;
case HostText:
recordHostChildrenToDelete(hostChildrenToDelete, unmountFiber);
diff --git a/packages/react-reconciler/src/completeWork.ts b/packages/react-reconciler/src/completeWork.ts
index 499e748..f8dc673 100644
--- a/packages/react-reconciler/src/completeWork.ts
+++ b/packages/react-reconciler/src/completeWork.ts
@@ -1,6 +1,6 @@
import { updateFiberProps } from 'react-dom/src/SyntheticEvent';
import { FiberNode } from './fiber';
-import { NoFlags, Update } from './fiberFlags';
+import { NoFlags, Ref, Update } from './fiberFlags';
import {
appendInitialChild,
createInstance,
@@ -15,6 +15,10 @@ import {
HostText
} from './workTags';
+function markRef(fiber: FiberNode) {
+ fiber.flags |= Ref;
+}
+
const appendAllChildren = (parent: Instance, workInProgress: FiberNode) => {
// 遍历workInProgress所有子孙 DOM元素,依次挂载
let node = workInProgress.child;
@@ -74,13 +78,20 @@ export const completeWork = (workInProgress: FiberNode) => {
// 不应该在此处调用updateFiberProps,应该跟着判断属性变化的逻辑,在这里打flag
// 再在commitWork中更新fiberProps,我准备把这个过程留到「属性变化」相关需求一起做
updateFiberProps(workInProgress.stateNode, newProps);
+ // 标记Ref
+ if (current.ref !== workInProgress.ref) {
+ markRef(workInProgress);
+ }
} else {
// 初始化DOM
const instance = createInstance(workInProgress.type, newProps);
// 挂载DOM
appendAllChildren(instance, workInProgress);
workInProgress.stateNode = instance;
-
+ // 标记Ref
+ if (workInProgress.ref !== null) {
+ markRef(workInProgress);
+ }
// TODO 初始化元素属性
}
// 冒泡flag
diff --git a/packages/react-reconciler/src/fiber.ts b/packages/react-reconciler/src/fiber.ts
index 3f419a5..23b35d3 100644
--- a/packages/react-reconciler/src/fiber.ts
+++ b/packages/react-reconciler/src/fiber.ts
@@ -112,7 +112,7 @@ export function createFiberFromElement(
element: ReactElement,
lanes: Lanes
): FiberNode {
- const { type, key, props } = element;
+ const { type, key, props, ref } = element;
let fiberTag: WorkTag = FunctionComponent;
if (typeof type === 'string') {
@@ -123,6 +123,7 @@ export function createFiberFromElement(
const fiber = new FiberNode(fiberTag, props, key);
fiber.type = type;
fiber.lanes = lanes;
+ fiber.ref = ref;
return fiber;
}
@@ -166,6 +167,7 @@ export const createWorkInProgress = (
// 数据
wip.memoizedProps = current.memoizedProps;
wip.memoizedState = current.memoizedState;
+ wip.ref = current.ref;
wip.lanes = current.lanes;
diff --git a/packages/react-reconciler/src/fiberFlags.ts b/packages/react-reconciler/src/fiberFlags.ts
index a89941e..7ac59c3 100644
--- a/packages/react-reconciler/src/fiberFlags.ts
+++ b/packages/react-reconciler/src/fiberFlags.ts
@@ -7,8 +7,10 @@ export const ChildDeletion = 0b00000000000000000000010000;
// useEffect
export const PassiveEffect = 0b00000000000000000000100000;
+export const Ref = 0b00000000000000000001000000;
-export const MutationMask = Placement | Update | ChildDeletion;
+export const MutationMask = Placement | Update | ChildDeletion | Ref;
+export const LayoutMask = Ref;
// 删除子节点可能触发useEffect destroy
export const PassiveMask = PassiveEffect | ChildDeletion;
diff --git a/packages/react-reconciler/src/fiberHooks.ts b/packages/react-reconciler/src/fiberHooks.ts
index 49667fb..9952414 100644
--- a/packages/react-reconciler/src/fiberHooks.ts
+++ b/packages/react-reconciler/src/fiberHooks.ts
@@ -68,12 +68,14 @@ export const renderWithHooks = (workInProgress: FiberNode, lane: Lane) => {
const HooksDispatcherOnMount: Dispatcher = {
useState: mountState,
- useEffect: mountEffect
+ useEffect: mountEffect,
+ useRef: mountRef
};
const HooksDispatcherOnUpdate: Dispatcher = {
useState: updateState,
- useEffect: updateEffect
+ useEffect: updateEffect,
+ useRef: updateRef
};
function mountState(
@@ -226,6 +228,18 @@ function areHookInputsEqual(nextDeps: TEffectDeps, prevDeps: TEffectDeps) {
return true;
}
+function mountRef(initialValue: T): { current: T } {
+ const hook = mountWorkInProgressHook();
+ const ref = { current: initialValue };
+ hook.memoizedState = ref;
+ return ref;
+}
+
+function updateRef(initialValue: T): { current: T } {
+ const hook = updateWorkInProgressHook();
+ return hook.memoizedState;
+}
+
export interface Effect {
tag: Flags;
create: TEffectCallback | void;
diff --git a/packages/react-reconciler/src/workLoop.ts b/packages/react-reconciler/src/workLoop.ts
index 254de1f..ac25f10 100644
--- a/packages/react-reconciler/src/workLoop.ts
+++ b/packages/react-reconciler/src/workLoop.ts
@@ -3,6 +3,7 @@ import {
commitHookEffectListDestroy,
commitHookEffectListMount,
commitHookEffectListUnmount,
+ commitLayoutEffects,
commitMutationEffects
} from './commitWork';
import { completeWork } from './completeWork';
@@ -338,6 +339,7 @@ function commitRoot(root: FiberRootNode) {
root.current = finishedWork;
// 阶段3/3:Layout
+ commitLayoutEffects(finishedWork, root);
executionContext = prevExecutionContext;
} else {
diff --git a/packages/react/index.ts b/packages/react/index.ts
index 1964204..88e19b0 100644
--- a/packages/react/index.ts
+++ b/packages/react/index.ts
@@ -15,6 +15,11 @@ export const useEffect: Dispatcher['useEffect'] = (create, deps) => {
return dispatcher.useEffect(create, deps);
};
+export const useRef: Dispatcher['useRef'] = (initialValue) => {
+ const dispatcher = resolveDispatcher() as Dispatcher;
+ return dispatcher.useRef(initialValue);
+};
+
export const __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {
currentDispatcher
};
diff --git a/packages/react/src/currentDispatcher.ts b/packages/react/src/currentDispatcher.ts
index 802cf05..0fc2ef9 100644
--- a/packages/react/src/currentDispatcher.ts
+++ b/packages/react/src/currentDispatcher.ts
@@ -3,6 +3,7 @@ import { Action } from 'shared/ReactTypes';
export type Dispatcher = {
useState: (initialState: (() => T) | T) => [T, Dispatch];
useEffect: (callback: (() => void) | void, deps: any[] | void) => void;
+ useRef: (initialValue: T) => { current: T };
};
export type Dispatch = (action: Action) => void;
diff --git a/packages/shared/ReactTypes.ts b/packages/shared/ReactTypes.ts
index 79f3388..f45e4dc 100644
--- a/packages/shared/ReactTypes.ts
+++ b/packages/shared/ReactTypes.ts
@@ -1,4 +1,4 @@
-export type Ref = any;
+export type Ref = { current: any } | ((instance: any) => void);
export type ElementType = any;
export type Key = string | null;
export type Props = {
From ec2c53d04b1b890401f67112cca44a89401cc816 Mon Sep 17 00:00:00 2001
From: Russellwzr
Date: Tue, 4 Jul 2023 11:24:29 +0800
Subject: [PATCH 12/15] fix: fix recordHostChildrenToDelete for fragment
deletion
---
packages/react-reconciler/src/commitWork.ts | 69 +++++++++++----------
1 file changed, 36 insertions(+), 33 deletions(-)
diff --git a/packages/react-reconciler/src/commitWork.ts b/packages/react-reconciler/src/commitWork.ts
index d7f8cd5..ec42195 100644
--- a/packages/react-reconciler/src/commitWork.ts
+++ b/packages/react-reconciler/src/commitWork.ts
@@ -25,7 +25,8 @@ import {
FunctionComponent,
HostComponent,
HostRoot,
- HostText
+ HostText,
+ Fragment
} from './workTags';
let nextEffect: FiberNode | null = null;
@@ -267,22 +268,23 @@ function getHostParent(fiber: FiberNode) {
console.error('getHostParent未找到hostParent');
}
-function recordHostChildrenToDelete(
- hostChildrenToDelete: FiberNode[],
- unmountFiber: FiberNode
-) {
- const lastOne = hostChildrenToDelete[hostChildrenToDelete.length - 1];
- if (!lastOne) {
- hostChildrenToDelete.push(unmountFiber);
- } else {
- let node = lastOne.sibling;
- while (node !== null) {
- if (unmountFiber === node) {
- hostChildrenToDelete.push(unmountFiber);
- }
- node = node.sibling;
+function recordHostChildrenToDelete(beginNode: FiberNode): FiberNode[] {
+ if (beginNode.tag !== Fragment) return [beginNode];
+ const hostChildrenToDelete: FiberNode[] = [];
+ const processQueue: FiberNode[] = [beginNode];
+ while (processQueue.length) {
+ const node = processQueue.shift();
+ if (node && node.tag !== Fragment) {
+ hostChildrenToDelete.push(node);
+ continue;
+ }
+ let childNode = node?.child;
+ while (childNode) {
+ processQueue.push(childNode);
+ childNode = childNode.sibling;
}
}
+ return hostChildrenToDelete;
}
/**
@@ -295,24 +297,25 @@ function commitDeletion(childToDelete: FiberNode, root: FiberRootNode) {
console.log('删除DOM、组件unmount', childToDelete);
}
// 在Fragment之前,只需删除子树的根Host节点,但支持Fragment后,可能需要删除同级多个节点
- const hostChildrenToDelete: FiberNode[] = [];
-
- commitNestedUnmounts(childToDelete, (unmountFiber) => {
- switch (unmountFiber.tag) {
- case HostComponent:
- recordHostChildrenToDelete(hostChildrenToDelete, unmountFiber);
- // 解绑ref
- safelyDetachRef(unmountFiber);
- return;
- case HostText:
- recordHostChildrenToDelete(hostChildrenToDelete, unmountFiber);
- return;
- case FunctionComponent:
- // effect相关操作
- commitPassiveEffect(unmountFiber, root, 'unmount');
- return;
- }
- });
+ const hostChildrenToDelete: FiberNode[] =
+ recordHostChildrenToDelete(childToDelete);
+
+ for (let i = 0; i < hostChildrenToDelete.length; i++) {
+ commitNestedUnmounts(hostChildrenToDelete[i], (unmountFiber) => {
+ switch (unmountFiber.tag) {
+ case HostComponent:
+ // 解绑ref
+ safelyDetachRef(unmountFiber);
+ return;
+ case HostText:
+ return;
+ case FunctionComponent:
+ // effect相关操作
+ commitPassiveEffect(unmountFiber, root, 'unmount');
+ return;
+ }
+ });
+ }
if (hostChildrenToDelete.length) {
const hostParent = getHostParent(childToDelete) as Container;
From c819b8dabb0e5d79e26f407ad1eaf6d3d972ec5a Mon Sep 17 00:00:00 2001
From: Russellwzr
Date: Thu, 6 Jul 2023 19:49:47 +0800
Subject: [PATCH 13/15] fix: add function component judgment for
recordHostChildrenToDelete to get host node
---
packages/react-reconciler/src/commitWork.ts | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/packages/react-reconciler/src/commitWork.ts b/packages/react-reconciler/src/commitWork.ts
index ec42195..773af9b 100644
--- a/packages/react-reconciler/src/commitWork.ts
+++ b/packages/react-reconciler/src/commitWork.ts
@@ -269,12 +269,13 @@ function getHostParent(fiber: FiberNode) {
}
function recordHostChildrenToDelete(beginNode: FiberNode): FiberNode[] {
- if (beginNode.tag !== Fragment) return [beginNode];
+ if (beginNode.tag !== Fragment && beginNode.tag !== FunctionComponent)
+ return [beginNode];
const hostChildrenToDelete: FiberNode[] = [];
const processQueue: FiberNode[] = [beginNode];
while (processQueue.length) {
const node = processQueue.shift();
- if (node && node.tag !== Fragment) {
+ if (node && node.tag !== Fragment && node.tag !== FunctionComponent) {
hostChildrenToDelete.push(node);
continue;
}
From e622d80a0124985d59e97f56bfd04eed63de8c83 Mon Sep 17 00:00:00 2001
From: Russellwzr
Date: Thu, 6 Jul 2023 20:06:31 +0800
Subject: [PATCH 14/15] fix: replace host node judement with
isHostTypeFiberNode
---
packages/react-reconciler/src/commitWork.ts | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/packages/react-reconciler/src/commitWork.ts b/packages/react-reconciler/src/commitWork.ts
index 773af9b..7d92e5e 100644
--- a/packages/react-reconciler/src/commitWork.ts
+++ b/packages/react-reconciler/src/commitWork.ts
@@ -268,14 +268,18 @@ function getHostParent(fiber: FiberNode) {
console.error('getHostParent未找到hostParent');
}
+function isHostTypeFiberNode(fiber: FiberNode) {
+ const tag = fiber.tag;
+ return [HostComponent, HostRoot, HostText].includes(tag);
+}
+
function recordHostChildrenToDelete(beginNode: FiberNode): FiberNode[] {
- if (beginNode.tag !== Fragment && beginNode.tag !== FunctionComponent)
- return [beginNode];
+ if (isHostTypeFiberNode(beginNode)) return [beginNode];
const hostChildrenToDelete: FiberNode[] = [];
const processQueue: FiberNode[] = [beginNode];
while (processQueue.length) {
const node = processQueue.shift();
- if (node && node.tag !== Fragment && node.tag !== FunctionComponent) {
+ if (node && isHostTypeFiberNode(node)) {
hostChildrenToDelete.push(node);
continue;
}
From 9d4b73eb7667eefdace7792b5eba5362d0faff8c Mon Sep 17 00:00:00 2001
From: Russellwzr
Date: Thu, 6 Jul 2023 20:19:17 +0800
Subject: [PATCH 15/15] fix: change hostChildren to childToDelete for FC
unmount
---
packages/react-reconciler/src/commitWork.ts | 30 ++++++++++-----------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/packages/react-reconciler/src/commitWork.ts b/packages/react-reconciler/src/commitWork.ts
index 7d92e5e..1185c71 100644
--- a/packages/react-reconciler/src/commitWork.ts
+++ b/packages/react-reconciler/src/commitWork.ts
@@ -305,22 +305,20 @@ function commitDeletion(childToDelete: FiberNode, root: FiberRootNode) {
const hostChildrenToDelete: FiberNode[] =
recordHostChildrenToDelete(childToDelete);
- for (let i = 0; i < hostChildrenToDelete.length; i++) {
- commitNestedUnmounts(hostChildrenToDelete[i], (unmountFiber) => {
- switch (unmountFiber.tag) {
- case HostComponent:
- // 解绑ref
- safelyDetachRef(unmountFiber);
- return;
- case HostText:
- return;
- case FunctionComponent:
- // effect相关操作
- commitPassiveEffect(unmountFiber, root, 'unmount');
- return;
- }
- });
- }
+ commitNestedUnmounts(childToDelete, (unmountFiber) => {
+ switch (unmountFiber.tag) {
+ case HostComponent:
+ // 解绑ref
+ safelyDetachRef(unmountFiber);
+ return;
+ case HostText:
+ return;
+ case FunctionComponent:
+ // effect相关操作
+ commitPassiveEffect(unmountFiber, root, 'unmount');
+ return;
+ }
+ });
if (hostChildrenToDelete.length) {
const hostParent = getHostParent(childToDelete) as Container;