需要对react的整个流程了解,可以看下前两篇文章
分为了两个流程,挂载和更新,区分挂载和更新就是依靠的当前处理的fiber节点所映射的另一个fiber节点是否存在
在renderWithHooks里初始化ReactCurrentDispatcher.current,然后再去执行的我们的组件函数,组件函数执行对应的hooks,hooks执行的时候ReactCurrentDispatcher.current.hooks执行
ReactCurrentDispatcher.current =
current === null || current.memoizedState === null
? HooksDispatcherOnMount
: HooksDispatcherOnUpdate;
currentlyRenderingFiber = workInProgress
HooksDispatcherOnMount(挂载阶段)
挂载阶段 走到mount的逻辑(这里只截取了常用的几个hooks)
const HooksDispatcherOnMount: Dispatcher = {
useCallback: mountCallback,
useEffect: mountEffect,
useImperativeHandle: mountImperativeHandle,
useLayoutEffect: mountLayoutEffect,
useMemo: mountMemo,
useReducer: mountReducer,
useRef: mountRef,
useState: mountState,
useDeferredValue: mountDeferredValue,
useTransition: mountTransition,
}
这里先看下简单的hooks
useCallback和useMemo

function mountCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
// mountWorkInProgressHook其实就是看是否存在memoizedState,不存在则创建一个hooks对象,存在则直接连接next
const hook = mountWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
// 然后更新hooks属性
hook.memoizedState = [callback, nextDeps];
return callback;
}
function mountWorkInProgressHook(): Hook {
const hook: Hook = {
memoizedState: null,
baseState: null,
baseQueue: null,
queue: null,
next: null,
};
// 第一个hooks执行的时候workInProgressHook为空了,所以就拿到当前处理的fiber节点,初始化
// 后续hooks的执行只需要通过next连接就行了
if (workInProgressHook === null) {
// currentlyRenderingFiber = workInProgress; 在renderWithHooks执行的时候就初始化了,指向了当前处理的fiber节点
//
currentlyRenderingFiber.memoizedState = workInProgressHook = hook;
} else {
workInProgressHook = workInProgressHook.next = hook;
}
return workInProgressHook;
}
那么useMemo也差不多,不过区别在于会将回调函数执行,然后存储的是Value值
function mountMemo<T>(
nextCreate: () => T,
deps: Array<mixed> | void | null,
): T {
const hook = mountWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
const nextValue = nextCreate();
hook.memoizedState = [nextValue, nextDeps];
return nextValue;
}
更新阶段的处理HooksDispatcherOnUpdate
const HooksDispatcherOnUpdate: Dispatcher = {
useCallback: updateCallback,
useContext: readContext,
useEffect: updateEffect,
useImperativeHandle: updateImperativeHandle,
useInsertionEffect: updateInsertionEffect,
useLayoutEffect: updateLayoutEffect,
useMemo: updateMemo,
useReducer: updateReducer,
useRef: updateRef,
useState: updateState,
useDebugValue: updateDebugValue,
useDeferredValue: updateDeferredValue,
useTransition: updateTransition,
};
还是以useCallback举例,这里对比新旧deps并没有使用严格等于判断,使用Object.is是为了处理NaN,+0,-0这些情况
function updateCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
const hook = updateWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
// 这里的是current,也就是当前页面展示的fiber的memoizedState
const prevState = hook.memoizedState;
if (prevState !== null) {
if (nextDeps !== null) {
const prevDeps: Array<mixed> | null = prevState[1];
// for循环deps,通过Object.is对比新旧deps,如果依赖没有变 则直接返回了直接的value
if (areHookInputsEqual(nextDeps, prevDeps)) {
return prevState[0];
}
}
}
hook.memoizedState = [callback, nextDeps];
return callback;
}
updateWorkInProgressHook
因为在renderWithHooks中会先将当前处理的fiber节点的memoizedState重置,所以updateWorkInProgressHook会将当前页面展现的fiber节点的memoizedState赋值给当前处理的fiber节点,然后通过next遍历,返回当前处理hooks
function updateWorkInProgressHook(): Hook {
let nextCurrentHook: null | Hook;
if (currentHook === null) {
const current = currentlyRenderingFiber.alternate;
if (current !== null) {
nextCurrentHook = current.memoizedState;
} else {
nextCurrentHook = null;
}
} else {
nextCurrentHook = currentHook.next;
}
let nextWorkInProgressHook: null | Hook;
if (workInProgressHook === null) {
nextWorkInProgressHook = currentlyRenderingFiber.memoizedState;
} else {
nextWorkInProgressHook = workInProgressHook.next;
}
if (nextWorkInProgressHook !== null) {
workInProgressHook = nextWorkInProgressHook;
nextWorkInProgressHook = workInProgressHook.next;
currentHook = nextCurrentHook;
} else {
currentHook = nextCurrentHook;
const newHook: Hook = {
memoizedState: currentHook.memoizedState,
baseState: currentHook.baseState,
baseQueue: currentHook.baseQueue,
queue: currentHook.queue,
next: null,
};
if (workInProgressHook === null) {
currentlyRenderingFiber.memoizedState = workInProgressHook = newHook;
} else {
workInProgressHook = workInProgressHook.next = newHook;
}
}
return workInProgressHook;
}
useEffect(mount阶段)

这一步其实也就是生成updateQueue环形链表,然后绑定到当前处理的fiber节点上

useEffect(update阶段)
这里的currentHook是只屏幕前展示的fiber对于的hooks,destory是在执行了对应effect回调函数的时候拿到返回的函数,然后在绑定到对应hooks节点的destory。

useEffect的处理便是在commit刚开始的阶段。最开始就处理的副作用列表,先之前effect链表的destory,然后将回调函数投入到调度队列中去。

useState(mount阶段)
初始化hook结构,赋值memoizedState,创建setStete

useState(update阶段)
update会走useReducer的逻辑

后面补一下setState,这一块挺复杂的
非特殊说明,本博所有文章均为博主原创。
共有 0 条评论