Skip to main content

dispatchSetState-hooks源码

function dispatchSetState(fiber, queue, action) {
{
if (typeof arguments[3] === 'function') {
error("State updates from the useState() and useReducer() Hooks don't support the " + 'second callback argument. To execute a side effect after ' + 'rendering, declare it in the component body with useEffect().');
}
}

console.log('=useState=app=dispatchSetState:', { fiber, queue, action })

var lane = requestUpdateLane(fiber);
// 创建一个 update 更新对象
var update = {
lane: lane,
action: action,
hasEagerState: false,
eagerState: null,
next: null
};

if (isRenderPhaseUpdate(fiber)) {
console.log('=useState=app=dispatchSetState调用enqueueRenderPhaseUpdate渲染阶段更新:')
enqueueRenderPhaseUpdate(queue, update);
} else {
enqueueUpdate$1(fiber, queue, update);
var alternate = fiber.alternate;

if (fiber.lanes === NoLanes && (alternate === null || alternate.lanes === NoLanes)) {
// 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.

var lastRenderedReducer = queue.lastRenderedReducer;
console.log('=useState=app=dispatchSetState 计算新状态', { queue, lastRenderedReducer })

if (lastRenderedReducer !== null) {
var prevDispatcher;

{
prevDispatcher = ReactCurrentDispatcher$1.current;
ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
}

try {
// currentState 旧值
var currentState = queue.lastRenderedState;
// currentState 新值
var 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.hasEagerState = true;
update.eagerState = eagerState;
console.log('=useState=app=dispatchSetState 对比新旧状态是否不同', { eagerState, currentState, objectIs: objectIs(eagerState, currentState) })
if (objectIs(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 {
{
ReactCurrentDispatcher$1.current = prevDispatcher;
}
}
}
}

var eventTime = requestEventTime();
console.log('%c=useState=app=重点:dispatchSetState调用scheduleUpdateOnFiberfiber更新', 'color:blueviolet')
var root = scheduleUpdateOnFiber(fiber, lane, eventTime);

if (root !== null) {
entangleTransitionUpdate(root, queue, lane);
}
}

markUpdateInDevTools(fiber, lane);
}