React 18 is the latest version of react 18. Some of the concepts in react 18 have been removed, such as Effect List, requestIdleCallback, etc. So hereby do a summary, convenient for everyone to learn, have a problem can leave a message at any time or private letter! (Interested students are also welcome to study together)
The core process is shown below
React is the most popular front-end framework. React has several core concepts: renderers, mediators, and schedulers
The renderer
React was originally just for DOM, but has since been adapted to support React Native as well. Hence the introduction of the concept of a “renderer” in the React internals.
The renderer is used to manage a React tree and make different calls depending on the underlying platform.
Renderers are also located in packages/ :
- React DOM RendererRender the React component into the DOM. It implements global
ReactDOM
API, this works on NPMreact-dom
The package. This is also available as a separate browser version, calledreact-dom.js
, export aReactDOM
Global object of.
- The React Native Renderer renders the React component as a Native view. This renderer is used inside React Native.
- The React Test Renderer renders the React component as a JSON tree. This is used for Jest’s snapshot test feature. Released as a react-test-renderer package on NPM.
Another officially supported renderer is React-Art. It used to be a separate GitHub repository, but now we add this to the main source tree.
Harmonic trap
Even though React DOM and React Native renderers are quite different, some logic needs to be shared. In particular, coordination algorithms need to be as similar as possible so that features like declarative rendering, custom components, state, lifecycle methods, and refs work consistently across platforms.
To solve this problem, different renderers share some code with each other. We call this part of the React “Reconciler.” When dealing with updates such as setState(), the Reconciler calls Render () on the components in the tree, and then decides whether to mount, update, or unload the reconciler.
There are no separate packs for Reconciler, as they do not have a public API for the time being. Instead, they are excluded from renderers like React DOM and React Native.
Stack reconciler
The “Stack” Reconciler is a solution for React 15 and earlier.
The Stack Reconciler creates the virtual DOM recursively and submits it to DOM Mutation, with the entire process synchronized and without the ability to interrupt the work or break it into chunks. If the component tree is very hierarchical, recursion can take up a lot of thread time, and the recursive update time exceeds 16ms, and the user interaction will stall.
Fiber reconciler
“Fiber” Reconciler is a new attempt to address the issues inherent in stack Reconciler, while addressing some of the legacy issues from history.
Fiber has become the default Reconciler since React 16.
Its main objectives are:
- Ability to slice interruptible tasks.
- Ability to adjust priorities, reset and reuse tasks.
- The ability to interleave parent and child elements to support layout in React.
- In the
render()
To return multiple elements.
- Better support for error boundaries.
nonIn concurrent mode, perform the following operations:
The top is a slider that will scale the entire chart area when you drag it
The flame map call information is as follows
Concurrent modeDo the same:
The flame map call information is as follows
By comparison, it is clear how smooth it is in concurrent mode
The scheduler
The scheduler mainly consists of two parts: time scheduling and priority scheduling
Tasks that the browser needs to perform per frame
Time scheduling
React schedulers react schedulers react schedulers
Method 1: isInputPending
Wicg.github. IO/IS-input-PE…
Developers need to make judgments today when running scripts that need to display something.
If the script may take a long time to run and the user makes some kind of input while this happens, the browser will need to wait until the script is complete before dispatching the input event. This creates a long delay before responding to input events, and the user experience is not great, so developers often break up long script tasks into smaller chunks to allow user agents to schedule events between blocks. Each time the script executes, it needs to somehow post a message, invoke a combination of requestAnimation frames and requestIdleCallback, or otherwise generate something that can be scheduled, which can then be invoked again at idle. Even in the best case, it can take many milliseconds for the script to run again each time it is generated. So unfortunately, it’s not a great user experience either, because part of the original script was delayed a long time, even though it took that long.
To avoid this trade-off, Facebook introduced and implemented the isInputPending() API in Chromium, which improves the responsiveness of web pages without significantly impacting performance.
The goal of the isInputPending API is that it will now allow developers to eliminate this trade-off. Instead of completely succumbing to user agents, and having to bear the cost of one or more event loops when they do, long-running scripts can now run to completion while still remaining responsive.
Currently, isInputPending API is only available in Chromium version 87 and is not implemented in other browsers.
2. SetImmediate
The first method is mainly used in the browser of Chromium engine, while the second method gives priority to the compatibility of IE in terms of design
This method is used to place long-running operations in a callback that is executed as soon as the browser completes the rest of the statement.
Only supports IE
Method 3: MessageChannel
The MessageChannel interface of the Channel Messaging API allows you to create a new MessageChannel and send data through its two MessagePort properties.
In the following example, you can see that a Channel object is instantiated using the MessageChannel constructor. When the iframe is loaded, we use the MessagePort.postMessage method to pass a message and Messagechannel. port2 to the Iframe. The handleMessage handler receives the information from the IFrame (listening for events using MessagePort.onMessage) and puts the data into innerHTML.
var channel = new MessageChannel();
var para = document.querySelector('p');
var ifr = document.querySelector('iframe');
var otherWindow = ifr.contentWindow;
ifr.addEventListener("load", iframeLoaded, false);
function iframeLoaded() {
otherWindow.postMessage('Hello from the main page! '.The '*', [channel.port2]);
}
channel.port1.onmessage = handleMessage;
function handleMessage(e) {
para.innerHTML = e.data;
}
Copy the code
Method 4: setTimeout
You know what I mean. Skip it
The slice time of the scheduler
Slice interval time is 5ms, the maximum interval time is 300ms, the source code is as follows
// Scheduler periodically yields in case there is other work on the main
// thread, like user events. By default, it yields multiple times per frame.
// It does not attempt to align with frame boundaries, since most tasks don't
// need to be frame aligned; for those that do, use requestAnimationFrame.
let yieldInterval = 5;
let deadline = 0;
// TODO: Make this configurable
// TODO: Adjust this based on priority?
const maxYieldInterval = 300;
let needsPaint = false;
Copy the code
Slice and React interact
Task split
The large task of recursive Reconciler traversing the VDOM is divided into a number of smaller tasks, each responsible for the processing of only one node.
-
workLoopSync or workLoopConcurrent
-
performUnitOfWork
Task suspends, resumes, and terminates
During the creation of the new workInProgress tree, Diff comparison will be made with the corresponding nodes of currentFiber to generate the corresponding FALgs. Meanwhile, the node objects corresponding to currentFiber will also be reused to reduce the overhead brought by the newly created objects. This means that the creation, update, suspend, restore, and terminate operations all occur during the creation of the workInProgress Tree. The workInProgress Tree build process is essentially a loop of executing tasks and creating the next task.
hang
When the first small task is complete, determine whether there is any free time in this frame, suspend the next task, remember the current suspended node, and give control to the browser to execute the higher-priority task.
restore
After the browser has rendered a frame, it determines whether the current frame has any time left, and if so resumes the pending task. If there are no tasks to deal with, the blending phase is complete and the rendering phase can begin.
Termination of
Not every update goes to commit. When a new update is triggered during reconciliation, the next task is executed to determine whether there is a higher priority task to be executed. If there is, the original task to be executed is terminated and a new workInProgressFiber tree building process is started to start the new update process. This avoids repeated update operations
Task priority
The following are the priorities of tasks provided in the source code, except for tasks with no priority, the lower the value of other tasks, the higher the priority
// No priority task
export const NoPriority = 0;
// Execute the task immediately
export const ImmediatePriority = 1;
// The user blocks the task
export const UserBlockingPriority = 2;
// Normal task
export const NormalPriority = 3;
// Low priority task
export const LowPriority = 4;
// Execute tasks in idle time
export const IdlePriority = 5;
Copy the code