renderRoot 调用 workLoopSync()
function workLoopSync() { // workInProgress = FiberNode while (workInProgress !== null) { workInProgress = performUnitOfWork(workInProgress); } }
performUnitOfWork
function performUnitOfWork(unitOfWork) { var current$$1 = unitOfWork.alternate; // startWorkTimer(unitOfWork) 初始化时 啥也没干 startWorkTimer(unitOfWork); // 赋值了些什么 setCurrentFiber(unitOfWork); var next = void 0; // enableProfilerTimer = true && (0 & 8) = 0 !== NoMode = 0 // 此条件返回false if (enableProfilerTimer && (unitOfWork.mode & ProfileMode) !== NoMode) { startProfilerTimer(unitOfWork); next = beginWork$$1(current$$1, unitOfWork, renderExpirationTime); stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); } else { // renderExpirationTime = 1073741823 next = beginWork$$1(current$$1, unitOfWork, renderExpirationTime); } resetCurrentFiber(); unitOfWork.memoizedProps = unitOfWork.pendingProps; if (next === null) { // If this doesn't spawn new work, complete the current work. next = completeUnitOfWork(unitOfWork); } ReactCurrentOwner$2.current = null; return next;}
updateHostRoot 重要
function updateHostRoot(current$$1, workInProgress, renderExpirationTime) { pushHostRootContext(workInProgress); var updateQueue = workInProgress.updateQueue; (function () { if (!(updateQueue !== null)) { { throw ReactError(Error('If the root does not have an updateQueue, we should have already bailed out. This error is likely caused by a bug in React. Please file an issue.')); } } })(); var nextProps = workInProgress.pendingProps; var prevState = workInProgress.memoizedState; var prevChildren = prevState !== null ? prevState.element : null; processUpdateQueue(workInProgress, updateQueue, nextProps, null, renderExpirationTime); var nextState = workInProgress.memoizedState; // Caution: React DevTools currently depends on this property // being called "element". var nextChildren = nextState.element; if (nextChildren === prevChildren) { // If the state is the same as before, that's a bailout because we had // no work that expires at this time. resetHydrationState(); return bailoutOnAlreadyFinishedWork(current$$1, workInProgress, renderExpirationTime); } var root = workInProgress.stateNode; if ((current$$1 === null || current$$1.child === null) && root.hydrate && enterHydrationState(workInProgress)) { // If we don't have any current children this might be the first pass. // We always try to hydrate. If this isn't a hydration pass there won't // be any children to hydrate which is effectively the same thing as // not hydrating. // This is a bit of a hack. We track the host root as a placement to // know that we're currently in a mounting state. That way isMounted // works as expected. We must reset this before committing. // TODO: Delete this when we delete isMounted and findDOMNode. workInProgress.effectTag |= Placement; // Ensure that children mount into this root without tracking // side-effects. This ensures that we don't store Placement effects on // nodes that will be hydrated. workInProgress.child = mountChildFibers(workInProgress, null, nextChildren, renderExpirationTime); } else { // Otherwise reset hydration state in case we aborted and resumed another // root. reconcileChildren(current$$1, workInProgress, nextChildren, renderExpirationTime); resetHydrationState(); } return workInProgress.child;}
beginWork$$1
beginWork$$1 = function (current$$1, unitOfWork, expirationTime) { var originalWorkInProgressCopy = assignFiberPropertiesInDEV(dummyFiber, unitOfWork); try { // current$$1 初始化创建的 FiberNode // unitOfWork 是 workInProgress // renderExpirationTime = 1073741823 return beginWork$1(current$$1, unitOfWork, expirationTime); } catch (originalError) { if (originalError !== null && typeof originalError === 'object' && typeof originalError.then === 'function') { // Don't replay promises. Treat everything else like an error. throw originalError; } // Keep this code in sync with renderRoot; any changes here must have // corresponding changes there. resetContextDependencies(); resetHooks(); // Unwind the failed stack frame unwindInterruptedWork(unitOfWork); // Restore the original properties of the fiber. assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); if (enableProfilerTimer && unitOfWork.mode & ProfileMode) { // Reset the profiler timer. startProfilerTimer(unitOfWork); } // Run beginWork again. invokeGuardedCallback(null, beginWork$1, null, current$$1, unitOfWork, expirationTime); if (hasCaughtError()) { var replayError = clearCaughtError(); // `InvokeGuardedCallback` sometimes sets an expando `_suppressLogging`. // Rethrow this error instead of the original one. throw replayError; } else { throw originalError; } }};
beginWork$1
function beginWork$1(current$$1, workInProgress, renderExpirationTime) { // current$$1 初始化创建的 FiberNode // unitOfWork 是 workInProgress // renderExpirationTime = 1073741823 // workInProgress.expirationTime = 1073741823 var updateExpirationTime = workInProgress.expirationTime; { // workInProgress._debugNeedsRemount = false if (workInProgress._debugNeedsRemount && current$$1 !== null) { // This will restart the begin phase with a new fiber. return remountFiber(current$$1, workInProgress, createFiberFromTypeAndProps(workInProgress.type, workInProgress.key, workInProgress.pendingProps, workInProgress._debugOwner || null, workInProgress.mode, workInProgress.expirationTime)); } } if (current$$1 !== null) { // current$$1.memoizedProps = null; // workInProgress.pendingProps = null; var oldProps = current$$1.memoizedProps; var newProps = workInProgress.pendingProps; function hasContextChanged() { // disableLegacyContext = false; if (disableLegacyContext) { return false; } else { // didPerformWorkStackCursor.current = false; return didPerformWorkStackCursor.current; } } if (oldProps !== newProps || hasContextChanged() || ( // workInProgress.type = null !== current$$1.type null 返回 false workInProgress.type !== current$$1.type)) { didReceiveUpdate = true; } // updateExpirationTime = 1073741823 < renderExpirationTime = 1073741823 // if 结果为false else if (updateExpirationTime < renderExpirationTime) { // ...省略 } } else { didReceiveUpdate = false; } // 常量 NoWork = 0 workInProgress.expirationTime = NoWork; switch (workInProgress.tag) { case IndeterminateComponent: // 2 { return mountIndeterminateComponent(current$$1, workInProgress, workInProgress.type, renderExpirationTime); } case LazyComponent: // 16 { var elementType = workInProgress.elementType; return mountLazyComponent(current$$1, workInProgress, elementType, updateExpirationTime, renderExpirationTime); } case FunctionComponent: // 0 { var _Component = workInProgress.type; var unresolvedProps = workInProgress.pendingProps; var resolvedProps = workInProgress.elementType === _Component ? unresolvedProps : resolveDefaultProps(_Component, unresolvedProps); return updateFunctionComponent(current$$1, workInProgress, _Component, resolvedProps, renderExpirationTime); } case ClassComponent: // 1 { var _Component2 = workInProgress.type; var _unresolvedProps = workInProgress.pendingProps; var _resolvedProps = workInProgress.elementType === _Component2 ? _unresolvedProps : resolveDefaultProps(_Component2, _unresolvedProps); return updateClassComponent(current$$1, workInProgress, _Component2, _resolvedProps, renderExpirationTime); } case HostRoot: // 3 return updateHostRoot(current$$1, workInProgress, renderExpirationTime); case HostComponent: // 5 return updateHostComponent(current$$1, workInProgress, renderExpirationTime); case HostText: // 6 return updateHostText(current$$1, workInProgress); case SuspenseComponent: // 13 return updateSuspenseComponent(current$$1, workInProgress, renderExpirationTime); case HostPortal: // 4 return updatePortalComponent(current$$1, workInProgress, renderExpirationTime); case ForwardRef: // 11 { var type = workInProgress.type; var _unresolvedProps2 = workInProgress.pendingProps; var _resolvedProps2 = workInProgress.elementType === type ? _unresolvedProps2 : resolveDefaultProps(type, _unresolvedProps2); return updateForwardRef(current$$1, workInProgress, type, _resolvedProps2, renderExpirationTime); } case Fragment: // 7 return updateFragment(current$$1, workInProgress, renderExpirationTime); case Mode: // 8 return updateMode(current$$1, workInProgress, renderExpirationTime); case Profiler: // 12 return updateProfiler(current$$1, workInProgress, renderExpirationTime); case ContextProvider: // 10 return updateContextProvider(current$$1, workInProgress, renderExpirationTime); case ContextConsumer: // 9 return updateContextConsumer(current$$1, workInProgress, renderExpirationTime); case MemoComponent: // 14 { var _type2 = workInProgress.type; var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); { if (workInProgress.type !== workInProgress.elementType) { var outerPropTypes = _type2.propTypes; if (outerPropTypes) { checkPropTypes_1(outerPropTypes, _resolvedProps3, // Resolved for outer only 'prop', getComponentName(_type2), getCurrentFiberStackInDev); } } } _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); return updateMemoComponent(current$$1, workInProgress, _type2, _resolvedProps3, updateExpirationTime, renderExpirationTime); } case SimpleMemoComponent: // 15 { return updateSimpleMemoComponent(current$$1, workInProgress, workInProgress.type, workInProgress.pendingProps, updateExpirationTime, renderExpirationTime); } case IncompleteClassComponent: // 17 { var _Component3 = workInProgress.type; var _unresolvedProps4 = workInProgress.pendingProps; var _resolvedProps4 = workInProgress.elementType === _Component3 ? _unresolvedProps4 : resolveDefaultProps(_Component3, _unresolvedProps4); return mountIncompleteClassComponent(current$$1, workInProgress, _Component3, _resolvedProps4, renderExpirationTime); } case DehydratedSuspenseComponent: // 18 { if (enableSuspenseServerRenderer) { return updateDehydratedSuspenseComponent(current$$1, workInProgress, renderExpirationTime); } break; } case SuspenseListComponent: // 19 { return updateSuspenseListComponent(current$$1, workInProgress, renderExpirationTime); } case FundamentalComponent: // 20 { if (enableFundamentalAPI) { return updateFundamentalComponent$1(current$$1, workInProgress, renderExpirationTime); } break; } } (function () { { { throw ReactError(Error('Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue.')); } } })();}
assignFiberPropertiesInDEV
function assignFiberPropertiesInDEV(target, source) { if (target === null) { target = createFiber(IndeterminateComponent, null, null, NoMode); } target.tag = source.tag; target.key = source.key; target.elementType = source.elementType; target.type = source.type; target.stateNode = source.stateNode; target.return = source.return; target.child = source.child; target.sibling = source.sibling; target.index = source.index; target.ref = source.ref; target.pendingProps = source.pendingProps; target.memoizedProps = source.memoizedProps; target.updateQueue = source.updateQueue; target.memoizedState = source.memoizedState; target.dependencies = source.dependencies; target.mode = source.mode; target.effectTag = source.effectTag; target.nextEffect = source.nextEffect; target.firstEffect = source.firstEffect; target.lastEffect = source.lastEffect; target.expirationTime = source.expirationTime; target.childExpirationTime = source.childExpirationTime; target.alternate = source.alternate; if (enableProfilerTimer) { target.actualDuration = source.actualDuration; target.actualStartTime = source.actualStartTime; target.selfBaseDuration = source.selfBaseDuration; target.treeBaseDuration = source.treeBaseDuration; } target._debugID = source._debugID; target._debugSource = source._debugSource; target._debugOwner = source._debugOwner; target._debugIsCurrentlyTiming = source._debugIsCurrentlyTiming; target._debugNeedsRemount = source._debugNeedsRemount; target._debugHookTypes = source._debugHookTypes; return target;}
setCurrentFiber
function setCurrentFiber(fiber) { { // typeof getCurrentFiberStackInDev === 'function' ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackInDev; current = fiber; phase = null; }}
startWorkTimer
var shouldIgnoreFiber = function (fiber) { // fiber.tag = 3 switch (fiber.tag) { case HostRoot: // 3 case HostComponent: // 5 case HostText: // 6 case HostPortal: // 4 case Fragment: // 7 case ContextProvider: // 10 case ContextConsumer: // 9 case Mode: // 8 return true; default: return false; }};function startWorkTimer(fiber) { // enableUserTimingAPI = true if (enableUserTimingAPI) { // supportsUserTiming = true // shouldIgnoreFiber(fiber) 返回 true if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { return; } // If we pause, this is the fiber to unwind from. currentFiber = fiber; if (!beginFiberMark(fiber, null)) { return; } fiber._debugIsCurrentlyTiming = true; }}