// Append the update to the end of the list. 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; }
functiondispatchAction<S, A>( fiber: Fiber, queue: UpdateQueue<S, A>, action: A, ) { const eventTime = requestEventTime(); const lane = requestUpdateLane(fiber);
const update: Update<S, A> = { lane, action, // <- 这里保存的是setXXX(newValue)里面的newValue值 eagerReducer: null, eagerState: null, next: (null: any), }; // 提到的queue在前文中的定义 // const queue = (hook.queue = { // pending: null, // dispatch: dispatchAction.bind( // null, // currentlyRenderingFiber, // queue, // ): any), // lastRenderedReducer: basicStateReducer, // lastRenderedState: (initialState: any), // }); // Append the update to the end of the list. 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) ) { // This is a render phase update. Stash it in a lazily-created map of // queue -> linked list of updates. After this render pass, we'll restart // and apply the stashed updates on top of the work-in-progress hook. // 这是一个渲染阶段的更新, 将其保存在一个延迟创建的队列(更新链表)映射中。 // 在这个更新结束之后,我们将会重新触发顶部的work-in-progress,将保存起来的更新进行应用。 // 这里做一个标记 并在render阶段触发更新 这种对应的是已经有多个update在fiber上的情况 didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true; } else { // 主要来说,这里是一个条件赋值行为(针对update对象) // 这里有个要点在于,当前update队列其实还是空的 所以可以直接计算下一步的state // 如果: 里面的值和当前一致就直接return退出不走下面的scheduleWork逻辑。 // 反之, 则执行scheduleUpdateOnFiber进行更新
// 以下是16.8版本时候的if判断 17.0.2有更新 但是贴出来感觉也有些参考意义 // currentlyRenderingFiber => workInProgress // if ( // fiber === currentlyRenderingFiber || // (alternate !== null && alternate === currentlyRenderingFiber) // ) { if ( fiber.lanes === NoLanes && (alternate === null || alternate.lanes === NoLanes) // fiber.lanes => fiber节点优先级 // fiber.lanes === NoLanes => fiber节点上没有更新需要执行 // 当fiber上不存在别的update,就不需要经过多个update进行合并计算state // 那么当前的update就是唯一的计算过程,即可以立刻算出结果 ) { // The queue is currently empty, which means we can eagerly compute the // next state before entering the render phase. If the new state is the // same as the current state, we may be able to bail out entirely. const lastRenderedReducer = queue.lastRenderedReducer; if (lastRenderedReducer !== null) { let prevDispatcher; try { const currentState: S = (queue.lastRenderedState: any); const eagerState = lastRenderedReducer(currentState, action); // Stash the eagerly computed state, and the reducer used to compute // it, on the update object. If the reducer hasn't changed by the // time we enter the render phase, then the eager state can be used // without calling the reducer again. update.eagerReducer = lastRenderedReducer; update.eagerState = eagerState; if (is(eagerState, currentState)) { // Fast path. We can bail out without scheduling React to re-render. // It's still possible that we'll need to rebase this update later, // if the component re-renders for a different reason and by that // time the reducer has changed. return; } } catch (error) { // Suppress the error. It will throw again in the render phase. } finally { } } } // 16.8版本的调用 scheduleWork(fiber, expirationTime); scheduleUpdateOnFiber(fiber, lane, eventTime); } }