-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
附录
该文件内对 Hooks 内一些常见的函数/概念做解析
updateWorkInProgressHook
功能:同时移动 currentHook 与 workInProgressHook 这两个指针
let currentHook: Hook | null = null;
let workInProgressHook: Hook | null = null;
...
function updateWorkInProgressHook(): Hook {
// 1. 移动 currentHook 指针
let nextCurrentHook: null | Hook;
/**
* currentHook / workInProgressHook 在初始化的时候都是null
*/
if (currentHook === null) {
const current = currentlyRenderingFiber.alternate; // 获取当前 wip fiber 对应的 current fiber 节点
if (current !== null) {
nextCurrentHook = current.memoizedState; // hooks 链表存储在 fiber 节点的 memoizedState 属性上
} else {
nextCurrentHook = null; // current fiber 节点为空,那也不可能存在对应的 hooks 链表
}
} else {
nextCurrentHook = currentHook.next; // 指针后移
}
let nextWorkInProgressHook: null | Hook;
/**
* 如果 WIP 的 hooks 为空,就把 WIP 上的 hooks 链表赋予它
* 否则 指针后移
*/
if (workInProgressHook === null) {
nextWorkInProgressHook = currentlyRenderingFiber.memoizedState;
} else {
nextWorkInProgressHook = workInProgressHook.next;
}
if (nextWorkInProgressHook !== null) {
// There's already a work-in-progress. Reuse it.
// 已经存在了 WIP 的 hooks 节点,复用即可
workInProgressHook = nextWorkInProgressHook;
nextWorkInProgressHook = workInProgressHook.next;
currentHook = nextCurrentHook;
} else {
// Clone from the current hook.
// WIP hooks 的数量多于 current hooks 的数量,直接报错
// 因此不允许通过条件判断包裹 hooks,必须保证每次调用的 hooks 数量一致
if (nextCurrentHook === null) {
throw new Error('Rendered more hooks than during the previous render.');
}
/**
* 借 currentHook 生成新的 workInProgressHook
*/
currentHook = nextCurrentHook;
const newHook: Hook = {
memoizedState: currentHook.memoizedState,
baseState: currentHook.baseState,
baseQueue: currentHook.baseQueue,
queue: currentHook.queue,
next: null,
};
/**
* 连接到 WIP Hook 的链表后面
*/
if (workInProgressHook === null) {
// This is the first hook in the list.
currentlyRenderingFiber.memoizedState = workInProgressHook = newHook;
} else {
// Append to the end of the list.
workInProgressHook = workInProgressHook.next = newHook;
}
}
return workInProgressHook;
}Metadata
Metadata
Assignees
Labels
No labels