1. The concept
After introducing Fiber, the overall update process is divided into the new process with fiber as the structure, and we can update and interrupt according to the priority.
The reactFiberScheduler.js file that has a lot of public variables in it and our understanding of those variables and the values that they’re called to modify elsewhere is key.
General process:
Summary: Make sure our low priority updates don’t affect browser animations and other renderings
2.schedulework
1. Find the corresponding fiberRoot node for update because the fiber passed by setState and ForceUpdate is the corresponding component
2. Reset the stack if certain conditions are met to store some important variables immediately
3. Request work scheduling if the conditions are met
Ps: We Button click on the list component to call setState, but it is our rootFiber that joins the scheduling queue, and all the nodes that join the scheduling queue are root nodes, because the new start is the root node
3.batchupdates
//requestwork.js
if (isBatchingUpdates) {/ /! Batch processing knowledge
// Flush work at the end of the batch.
if (isUnbatchingUpdates) {
/ /... unless we're inside unbatchedUpdates, in which case we should
// flush it now.
nextFlushedRoot = root;
nextFlushedExpirationTime = Sync;
performWorkOnRoot(root, Sync, true);
}
return; / / if it is a batch update direct return does not perform the following performSyncWork, scheduleCallbackWithExpirationTime
}
// TODO: Get rid of Sync and use current time?
/ /! A more expirationTime type to call the associated scheduling method
if (expirationTime === Sync) {
performSyncWork();/ /! Synchronization cannot be broken
} else {
scheduleCallbackWithExpirationTime(root, expirationTime);/ /! asynchronous
}
Copy the code
Let’s isBatchingUpdates = true then return the task directly in requestWork and then finally execute sync update fiber update once.
All event callbacks follow the batchUpdates logic
function batchedUpdates<A.R> (fn: (a: A) => R, a: A) :R {
const previousIsBatchingUpdates = isBatchingUpdates;
isBatchingUpdates = true;
try {
return fn(a);/ /! All setstates in callback functions that execute events and so on are added to the udpateQueue
} finally {
/ /! Determine if you currently want batchUpdates
isBatchingUpdates = previousIsBatchingUpdates;
if(! isBatchingUpdates && ! isRendering) { performSyncWork();/ /! Synchronous execution replaces updating in requestWork}}}Copy the code
The normal node render calls unbatchedUpdates isBatchingUpdates to be false, then updates to the Fiber queue, and then requestWork isBatchingUpdates to be false Go to the situation of task scheduling
/ /! Batch update
DOMRenderer.unbatchedUpdates(() = > {
if(parentComponent ! =null) {
root.legacy_renderSubtreeIntoContainer(
parentComponent,
children,
callback,
);
} else {
/ /! Root is the ReactRoot object that calls the Render method
root.render(children, callback);/ /! Children is the child node rendered to the Container}});Copy the code
//unbatchedUpdates function unbatchedUpdates<A, R>(fn: (a: A) => R, a: A): R { if (isBatchingUpdates && ! isUnbatchingUpdates) { isUnbatchingUpdates = true; try { return fn(a); } finally { isUnbatchingUpdates = false; } } return fn(a); }Copy the code
Isbatching will only set isBatching to true at the start of the event callback function or when you call batchUpdate yourself and will be false at the end of the task so other places like (dom first render) will be false
The event is related to the interactiveUpdates$1 function
setTimeout(() = > {
this.countNumber()
}, 0)
Copy the code
In this case, the whole function is executing inside the FN. At this point, the setTimeout is read and the batchupdates callback exits before the setTimeout is executed So if I trigger setTimeout, I’m not going to do batchupdates, If batchUpdates are false, the view will be updated. If batchUpdates are false, the view will be updated
setTimeout(() => {
batchedUpdates(() => this.countNumber())
}, 0)
Copy the code
This code does not return to requestWork directly, but to set batchUodates to true via batchedUpdates. This code returns to Finaly via performSync
isBatchingInteractiveUpdates = previousIsBatchingInteractiveUpdates;
isBatchingUpdates = previousIsBatchingUpdates;
if(! isBatchingUpdates && ! isRendering) { performSyncWork(); }Copy the code
Why before you take this part of the logic of previousIsBatchingInteractiveUpdates is true then before because they were afraid to said outer layer or in the process of batch update Because the end of the batch must be false. If we’re still in the update process we just return them to refresh all update ue queues in the outermost batch update.
Remember that the direct binding event has two layers: 1. Intertive 2. Batchupdates
Call batchedUpdates directly and there’s only one layer where prebatchupdates, the batchUpdatese of the outer layer is false so performSyncWork for that layer
The second parameter of setState is stored as a callback function in the Update callback until the update Ue execution is complete
**ps:** Asynchronous setState functions are batch executed in the requestWork, while asynchronous setState functions are batch executed in the requestWork
The flow chart