In the previous article, we parsed the generation of FiberRoot in the Render process. This article focuses on the other part of the Render step. Queues, updates, and so on are involved. But we’re not going to focus on that, we’re going to look at it later.
1.legacyRenderSubtreeIntoContainer
Remember from the previous article that this function entry started the render process and we neglected to update the code as follows:
/** * parentComponent: the parent, which can be passed as the first argument in null * children reactdom.render () or reactdom.hydrate (). Container: true for server rendering, false for client rendering, we are working on client-side rendering * callback: This is the callback function that needs to be executed after the component is rendered. I haven't used this parameter before, so you can try **/
function legacyRenderSubtreeIntoContainer(parentComponent: ? React$Component<any, any>,children: ReactNodeList,container: Container,forceHydrate: boolean,callback: ?Function.) {
/ /... Omit the fiberRoot initialization
// The first time root is empty, initialize root already fiberRoot, refer to the previous article
if(! root) {/ /... The root creation step is omitted
fiberRoot = root._internalRoot;
// unbatchedUpdates: Initial mounts should not be batch processed
unbatchedUpdates(() = > {
updateContainer(children, fiberRoot, parentComponent, callback);
});
} else {
// Instead of initializing the hang, call updateContainer
fiberRoot = root._internalRoot;
updateContainer(children, fiberRoot, parentComponent, callback);
}
return getPublicRootInstance(fiberRoot);
}
Copy the code
2. unbatchedUpdates
What is batch processing? For example, we often use setState. When we set the value multiple times, react does not render multiple times and optimizes it to a single update. UnbatchedUpdates don’t batch render. In the unbatchedUpdates function below, you can see that we just changed the value of executionContext, which means no batch processing.
// If the value is set three times, it is merged and executed only once
this.setState({ name: 'xiaodong' })
this.setState({ name: 'xiaoxue' })
this.setState({ name: 'xiaomei' })
function unbatchedUpdates<A.R> (fn: (a: A) => R, a: A) :R {
// executionContext: 0b0000000
// BatchedContext: 0b0000001
// LegacyUnbatchedContext: 0b0001000
const prevExecutionContext = executionContext;
// Remove BatchedContext from the BatchedContext operator
// executionContext: Note that ReactFiberWorkLoop is a global object that can be retrieved directly in subsequent execution functions
executionContext &= ~BatchedContext; // 0b0000000 & 0b1111110
executionContext |= LegacyUnbatchedContext; // Operator representation contains LegacyUnbatchedContext
try {
return fn(a); // Call the callback function
} finally {
executionContext = prevExecutionContext; // Restore executionContext when an exception occurs
if (executionContext === NoContext) {
Flushes the planned immediate callback in this batchflushSyncCallbackQueue(); }}}Copy the code
3. updateContainer
The first parameter in /** ** children reactdom.render () or reactdom.hydrate () can be understood as the root component. Container: : ReactElement object in render FiberRoot * parentComponent: the parentComponent that can be passed null * callback: the callback that needs to be executed after the component is rendered. I haven't used this parameter, you can try **/
export function updateContainer(element: ReactNodeList,container: OpaqueRoot,parentComponent: ? React$Component<any, any>,callback: ?Function) :Lane {
// Get the current rootFiber object
const current = container.current;
// Get the time the program has been running so far for prioritization
const eventTime = requestEventTime();
// The current batch update configuration is a global object, which will be expanded later
const suspenseConfig = requestCurrentSuspenseConfig();
// SyncLane = 1. In the future, the return value of concurrent and asynchronous will be different. Currently, only synchronous mode is used
const lane = requestUpdateLane(current, suspenseConfig);
// Get the context of the current node and its children
// The first execution returns an emptyContext, which is a {}
const context = getContextForSubtree(parentComponent); / / {}
if (container.context === null) {
container.context = context; // fiberRoot.context = {}
} else {
container.pendingContext = context;
}
Initialize the updateQueue queue of the Current (HostRootFiber) object
1.1 Create an update object
const update = createUpdate(eventTime, lane, suspenseConfig);
// Set the payload of the update object. The payload of the element is set to
.
update.payload = { element };
// 1.3 Add the update object to the current Fiber update column (in this case, RootFiber)
enqueueUpdate(current, update);
// Schedule and update the current(HostRootFiber) object
scheduleUpdateOnFiber(current, lane, eventTime);
return lane;
}
Copy the code
4. requestEventTime
Gets the time the program has been running so far for prioritization.
let currentEventTime = -1;
function requestEventTime() {
// executionContext = 0b001000, unbatchedUpdates function Chinese calculated value
// RenderContext = 0b010000;
// CommitContext = 0b100000;
if((executionContext & (RenderContext | CommitContext)) ! == NoContext) {// We are inside React, so we can read the actual time
return now();
}
// We are not inside React, so we might be in the middle of browser events.
if(currentEventTime ! == NoTimestamp) {// Use the same start time for all updates until we enter React again
return currentEventTime;
}
// This is the first update since React was created. Calculate the new start time.
currentEventTime = now();
return currentEventTime;
}
Copy the code
5. At the end
The Render section is done, and the scheduling involved in this will be studied in the component update section.
6. Write at the end
The Render section is done, and the scheduling involved in this will be studied in the component update section. If there are any incorrect places, please correct me, thank you.
- React source series 1: React API
- React Render FiberRoot
- React source series 3: React.Render process 2 update
- React Fiber
- React Scheduler Scheduler
- React Scheduler….