05.加入优先级的初始化渲染
react-reconciler/src/ReactFiberRoot.js
diff
+import { NoLanes } from './ReactFiberLane';
function FiberRootNode(containerInfo) {
this.containerInfo = containerInfo;
+ this.pendingLanes = NoLanes;
}react-reconciler/src/ReactFiber.js
js
import { NoLanes } from './ReactFiberLane';
export function FiberNode(tag, pendingProps, key) {
...
this.lanes = NoLanes;
}react-reconciler/src/ReactFiberReconciler.js
js
import { createFiberRoot } from "./ReactFiberRoot";
import { createUpdate, enqueueUpdate } from "./ReactFiberClassUpdateQueue";
import { scheduleUpdateOnFiber, requestUpdateLane } from "./ReactFiberWorkLoop";
export function createContainer(containerInfo) {
return createFiberRoot(containerInfo);
}
export function updateContainer(element, container) {
const current = container.current;
const lane = requestUpdateLane(current);
const update = createUpdate(lane);
update.payload = { element };
const root = enqueueUpdate(current, update, lane);
scheduleUpdateOnFiber(root, current, lane);
}react-reconciler/src/ReactFiberWorkLoop.js
js
export function requestUpdateLane() {
const updateLane = getCurrentUpdatePriority();
if (updateLane !== NoLanes) {
return updateLane;
}
const eventLane = getCurrentEventPriority();
return eventLane;
}js
import {
scheduleCallback as Scheduler_scheduleCallback,
shouldYield,
ImmediatePriority as ImmediateSchedulerPriority,
UserBlockingPriority as UserBlockingSchedulerPriority,
NormalPriority as NormalSchedulerPriority,
IdlePriority as IdleSchedulerPriority,
} from "./scheduler";
import {
NoLanes, markRootUpdated, getNextLanes,
getHighestPriorityLane, SyncLane
} from './ReactFiberLane';
import {
getCurrentUpdatePriority,
lanesToEventPriority,
DiscreteEventPriority,
ContinuousEventPriority,
DefaultEventPriority,
IdleEventPriority
} from './ReactEventPriorities'
import { getCurrentEventPriority } from 'react-dom-bindings/src/client/ReactDOMHostConfig'
let workInProgressRoot = null;
let workInProgressRenderLanes = NoLanes;diff
-export function scheduleUpdateOnFiber(root, fiber, lane) {
+export function scheduleUpdateOnFiber(root, fiber, lane) {
+ markRootUpdated(root, lane);
ensureRootIsScheduled(root);
}js
function ensureRootIsScheduled(root) {
const nextLanes = getNextLanes(root, NoLanes);
let newCallbackPriority = getHighestPriorityLane(nextLanes);
if (newCallbackPriority === SyncLane) {
} else {
let schedulerPriorityLevel;
switch (lanesToEventPriority(nextLanes)) {
case DiscreteEventPriority:
schedulerPriorityLevel = ImmediateSchedulerPriority;
break;
case ContinuousEventPriority:
schedulerPriorityLevel = UserBlockingSchedulerPriority;
break;
case DefaultEventPriority:
schedulerPriorityLevel = NormalSchedulerPriority;
break;
case IdleEventPriority:
schedulerPriorityLevel = IdleSchedulerPriority;
break;
default:
schedulerPriorityLevel = NormalSchedulerPriority;
break;
}
Scheduler_scheduleCallback(schedulerPriorityLevel, performConcurrentWorkOnRoot.bind(null, root));
}
}diff
function performConcurrentWorkOnRoot(root, timeout) {
+ const nextLanes = getNextLanes(root, NoLanes);
+ if (nextLanes === NoLanes) {
+ return null;
+ }
+ renderRootSync(root, nextLanes);
const finishedWork = root.current.alternate;
root.finishedWork = finishedWork;
commitRoot(root);
return null;
}
+function prepareFreshStack(root, renderLanes) {
+ if (root !== workInProgressRoot || workInProgressRenderLanes !== renderLanes) {
workInProgress = createWorkInProgress(root.current, null);
+ }
+ workInProgressRenderLanes = renderLanes;
finishQueueingConcurrentUpdates();
}
+function renderRootSync(root, renderLanes) {
+ prepareFreshStack(root, renderLanes);
workLoopSync();
}diff
function performUnitOfWork(unitOfWork) {
const current = unitOfWork.alternate;
+ const next = beginWork(current, unitOfWork, workInProgressRenderLanes);
unitOfWork.memoizedProps = unitOfWork.pendingProps;
if (next === null) {
completeUnitOfWork(unitOfWork);
} else {
workInProgress = next;
}
}diff
function commitRoot(root) {
const { finishedWork } = root;
+ workInProgressRoot = null;
+ workInProgressRenderLanes = null;
if ((finishedWork.subtreeFlags & Passive) !== NoFlags
|| (finishedWork.flags & Passive) !== NoFlags) {
if (!rootDoesHavePassiveEffect) {
rootDoesHavePassiveEffect = true;
scheduleCallback(NormalSchedulerPriority, flushPassiveEffect);
}
}
const subtreeHasEffects = (finishedWork.subtreeFlags & MutationMask) !== NoFlags;
const rootHasEffect = (finishedWork.flags & MutationMask) !== NoFlags;
if (subtreeHasEffects || rootHasEffect) {
commitMutationEffectsOnFiber(finishedWork, root);
commitLayoutEffects(finishedWork, root);
if (rootDoesHavePassiveEffect) {
rootDoesHavePassiveEffect = false;
rootWithPendingPassiveEffects = root;
}
}
root.current = finishedWork;
}react-reconciler/src/ReactFiberHooks.js
js
import { scheduleUpdateOnFiber, requestUpdateLane } from "./ReactFiberWorkLoop";
import { NoLane, NoLanes } from './ReactFiberLane';diff
function dispatchSetState(fiber, queue, action) {
+ const lane = requestUpdateLane();
const update = {
+ lane,
action,
hasEagerState: false,
eagerState: null,
next: null
}
+ const alternate = fiber.alternate;
+ if (fiber.lanes === NoLanes && (alternate === null || alternate.lanes == NoLanes)) {
const { lastRenderedReducer, lastRenderedState } = queue;
const eagerState = lastRenderedReducer(lastRenderedState, action);
update.hasEagerState = true;
update.eagerState = eagerState;
if (Object.is(eagerState, lastRenderedState)) {
return;
}
+ }
+ const root = enqueueConcurrentHookUpdate(fiber, queue, update, lane);
+ scheduleUpdateOnFiber(root, fiber, lane);
}diff
function mountReducer(reducer, initialArg) {
const hook = mountWorkInProgressHook();
hook.memoizedState = initialArg;
const queue = {
pending: null,
dispatch: null,
+ lastRenderedReducer: reducer,
+ lastRenderedState: initialArg
}
hook.queue = queue;
const dispatch = (queue.dispatch = dispatchReducerAction.bind(null, currentlyRenderingFiber, queue));
return [hook.memoizedState, dispatch];
}