一、回顾更新过程
举个例子,这个问题让我先来回顾一下useState这个的流程,比如说我们有这样一个触发更新的函数
function toUpdate(){
setNumber(number + 1);
setNumber(number + 2);
setName("wuyz")
}
当点击调用setNumber的时候,事实上是调用的dispatchAction函数
function dispatchAction<S, A>(
fiber: Fiber,
queue: UpdateQueue<S, A>,
action: A,
) {
const lane = requestUpdateLane(fiber);
const update: Update<S, A> = {
lane,
action,
eagerReducer: null,
eagerState: null,
next: (null: any),
};
//下面这块代码是创建的更新队列
const pending = queue.pending;
if (pending === null) {
// This is the first update. Create a circular list.
update.next = update;
} else {
update.next = pending.next;
pending.next = update;
}
queue.pending = update;
const alternate = fiber.alternate;
if (
fiber === currentlyRenderingFiber ||
(alternate !== null && alternate === currentlyRenderingFiber)
) {
didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true;
} else {
if (
fiber.lanes === NoLanes &&
(alternate === null || alternate.lanes === NoLanes)
) {
const lastRenderedReducer = queue.lastRenderedReducer;
if (lastRenderedReducer !== null) {
let prevDispatcher;
try {
const currentState: S = (queue.lastRenderedState: any);
const eagerState = lastRenderedReducer(currentState, action);
update.eagerReducer = lastRenderedReducer;
update.eagerState = eagerState;
//如果两者相等那就没必要调用更新了
if (is(eagerState, currentState)) {
return;
}
}
}
}
//更新队列整理好之后调用更新
scheduleUpdateOnFiber(fiber, lane, eventTime);
}
}
事实上dispatchAction主要就是起到一个整理更新队列的作用,接下来就是调度的一系列任务了。
在更新函数组件里会调用 renderWithHooks,函数里面有一句
let children = Component(props, secondArg);
component是我们的组件,比如App() 然后执行这个函数组件,会再一次执行我们之前在函数顶部写过的useState等钩子函数,就是对useState这些重新执行(不过这次会根据current !== null得出是update阶段),那么这个时候就可以看到useState调用的是updateReducer而不是挂载mountReducer了,updateReducer里面有行代码是这样的.
// 获取的是之前dispatchAction函数里
// 排列好的更新队列,updateWorkInProgressHook是获取最新的hook
const hook = updateWorkInProgressHook();
const queue = hook.queue;
updateWorkInProgressHook每次获取的WorkInProgress这棵树上的最新的hook,如果说在这次的renderWithHooks函数执行过程中,有一个hook没执行,那么这个hook的数据state就会被下一个state拿去用,这显然是不合理的。顺便提一下,renderWithHooks返回的是最新的fiber对象
以上的我在最近看react源码的一些见解,同时也从别人的文章里学了很多,如果有错误的欢迎大家指出~~
ps:hook的数据结构
const newHook: Hook = {
memoizedState: null,
baseState: null,
baseQueue:null,
queue: null,
next: null,
};