1.react package
React Core Functionality and API This package provides core functionality for creating React components, state management, lifecycle methods, and more. This package is a must for any project using React.
React Element Creation:react
provides theReact.createElement()
method, which allows developers to define UI structures. This is mostly done indirectly through the JSX syntax, as JSX is compiled intoReact.createElement()
calls.
Component and Class Definitions: Provides the basic mechanism for creating components, including theReact.Component
andReact.PureComponent
base classes. These classes provide the ability to define the lifecycle methods, state (state
), and properties (props
) of a component.
Hooks: As of React 16.8,react
introduces the Hooks API, includinguseState
,useEffect
,useContext
,useReducer
, etc., which enables the use of state management and lifecycle features in function components.
Context: Provides a Context API, i.e.React.createContext
,Context.Provider
,Context.Consumer
, etc., which can pass data directly across component hierarchies without having to pass it layer by layer through props.
Fragment: React.fragment (<>...</>
) is a way to make a component return multiple elements.
Refs: APIs such asReact.createRef
,React.forwardRef
are provided to manage direct references to DOM nodes or component instances.
Error Boundary: ThecomponentDidCatch
lifecycle method in theReact.Component
class allows a component to intercept JS errors in its child component tree and log them.
Tool Functions: Thereact
package also contains functions such asReact.Children
and other helper functions for working with children props and other different kinds of tools.
2.react-dom
react-dom
package is a package in the React ecosystem that is specialized for the web browser environment and provides the methods and APIs needed to interact with the DOM (Document Object Model) in the browser.
Rendering:ReactDOM.render()
is one of the most important methods of thereact-dom
package, rendering React elements into the specified DOM container. React version 18 introduced thecreateRoot()
function for the same purpose, but in a more advanced way.
Interacting with the browser: In addition to rendering elements,react-dom
also handles binding and unbinding of event handlers and other tasks that require direct interaction with the browser’s DOM API.
Lifecycle Hook:react-dom
is responsible for calling the component’s lifecycle methods, such as mounting (componentDidMount
), updating (componentDidUpdate
), and unloading (componentWillUnmount
) of the component.
Portals:react-dom
provides an API for creating portals. Portals provide a way to render child nodes to DOM nodes that exist outside of the parent component.
Server-Side Rendering (SSR) :react-dom/server
provides APIs for server-side rendering. These includerenderToString()
andrenderToStaticMarkup()
, which convert React elements to HTML strings, respectively, and can be used to generate the initial rendering of a web page.
Testing Tools:react-dom
providesreact-dom/test-utils
, a set of tools to assist in testing component behavior.
Find DOM node:react-dom
also provides theReactDOM.findDOMNode()
method, which can get the DOM node of the component, but it is not recommended for performance and code clarity reasons.
Hydration: When server-side rendering (SSR) is used to generate HTML for a React component and it is loaded on the client,react-dom
can “hydrate” that HTML, which has the effect of reconnecting event handlers, etc., without re-rendering the DOM.
In the React architecture, the react
library is responsible for defining how components are created and managing state, while the react-dom
library is React’s rendering engine and handles how these components are actually displayed and updated in the browser. This separation allows the same React components to work in different environments (e.g. Web, Native, VR, etc.) with different rendering engines (e.g. react-dom
, react-native
).
3.react-reconciler
It provides the ability to define custom renderers and encapsulates React’s reconciliation algorithm, which is used to calculate updates. With react-reconciler
, developers can create new renderers to render React components to different platforms and rendering environments, such as WebGL or a command line interface (CLI).
Reconciliation Algorithm:react-reconciler
implements React’s Fiber Reconciliation Algorithm, an efficient algorithm for coordinating and rendering React element trees. It allows React to pause, interrupt, and reuse work during rendering to accommodate other work in the main thread.
Platform independence: Abstracting the reconciliation process from platform-specific details means that the same set of React code can be used for rendering on different platforms, and each platform only needs its own renderer.
Custom Rendering:react-reconciler
allows developers to create new rendering backends for a variety of output targets. The renderer is responsible for maintaining the host environment’s tree of elements and responding to create, update, or delete operations coming from React.
Core API:react-reconciler
package provides aReconciler(config)
function. Developers can provide a configuration object (config
) that contains various method implementations for the host environment (e.g., browser DOM, React Native, etc.). These methods include creating, deleting, and updating nodes in the host environment, as well as inserting nodes.
Custom Component Lifecycle: In addition,react-reconciler
allows developers to implement custom renderer lifecycle methods, such as updating or cleaning up resources at specific points in time.
Experimental feature support: Renderers built withreact-reconciler
have access to the latest features and improvements being developed by the React core team, such as providing support for concurrency mode.
4. scheduler [was not available before 16]
It focuses on optimizing performance, especially related to task scheduling.The React team introduced this package to enable advanced features like Concurrent Mode, which optimizes rendering performance by orchestrating tasks with different priorities, especially in the case of large updates or when performing costly computations on the main thread.
Task Scheduling: Thescheduler
package allows React to schedule tasks based on their priority. This means that React can decide when to execute a task and how to insert more urgent work into important renders and updates.
Priority settings: This provides the ability to set the priority of different tasks so that React can prioritize high-priority tasks, such as user interactions, while deferring less urgent tasks, such as data prefetching, to a later time.
Interrupting and Resuming Work: While executing long tasks,scheduler
can interrupt them to ensure that the main thread is not blocked, thus keeping the application responsive. Later, once the main thread becomes free,scheduler
can resume these interrupted tasks.
Coordinate Multiple Tasks: It manages and coordinates the execution of multiple tasks, ensuring that tasks are executed in the correct order and priority.
Avoiding main thread blocking: Thescheduler
package supports the browser’srequestIdleCallback()
API and in this way allows tasks to be executed when the main thread is idle, which reduces blocking of the main thread and thus improves application performance.
Advanced Scheduling: With experimental concurrency features, developers can utilize thescheduler
package for more advanced scheduling in large applications with complex state logic and data access requirements.
Two loops in react
1. Task Scheduling Loop
The logic of the main macro to schedule is each task (
task
), and do not care about the specific task is what to do, the specific task is actually the execution of the callback function.react-reconciler
After receiving(add, delete, update), and will not immediately construct the
fiber
tree, but go to thescheduler
scheduling center to registertask
,task
into thetask
queue to wait for the right time to call the callbacks in the execution oftask
2. fiber construction loop
fiber
It takes as the data structure, performs depth-first traversal from top to bottom, constructs the fiber
tree, and passes commitRoot(FiberRootNode)
into react-dom
for dom
rendering.
III. Relationship between the two cycles
From the above figure we can see that a task
mainly consists of ( fiber
tree construction, DOM
rendering, scheduling detection), react-reconciler
registered task at a certain time for the call, the call will go to the realization of the task, which include
-
fiber tree
tectonic (geology) -
DOM
add washes of ink or color to a drawing (Chinese painting)
Scheduling Detection And thefiber
construction loop is one of thetask
implementation aspects, where tasks all reconstruct afiber
tree.
Four, several objects of react
The following examples are all drawn with the app.js
file in the source directory of the previous build!!!!
JSX
In the last two posts we’ve explored the principle of jsx
, where jsx
is eventually converted by babel
into createElement
which then creates the ReactElement
ReactElement
1. Basic introduction
ReactElement
is the most basic unit of theReact
application. It is a lightweight description of a part of the UI and is actually a regularjs
object that can represent aDOM
node or other component part. The element (Element
) object contains the component type (e.g.div、span
or other custom component), attributes, and child elements. Elements are immutable; once created, their children or attributes cannot be changed. When you update the UI, React creates a new tree of elements to represent the newUI
state.
react
Will go and build thefiber
tree based on the ReactElement
2. Data structure
{
$$typeof: Symbol.for('react.element'),
type: 'div',
key: null,
ref: null,
props: {
className: 'sidebar',
children: 'Content here'
},
_owner: null,
_store: {},
_self: null,
_source: null,
}
fiber
Basic Introduction
Fiber
is a new coordination algorithm (one of the core algorithms of React) introduced in the React 16
version. It was introduced primarily to optimize the rendering flow of React
so that it can perform more efficient update and task scheduling. The introduction of the Fiber architecture addresses some of the limitations of the traditional React
virtual DOM
algorithm (recursive comparison update strategy), such as the following:
Interruptible Work: In older algorithms, once a rendering job is started, it must be completed until the entire virtualDOM
tree has been compared, which can cause the main thread to be occupied for long periods of time, affecting the performance of animations, layouts, and input responses. The Fiber architecture introduces the ability to break up the rendering job into small chunks, enabling work to be interrupted and resumed, allowing the main thread to perform more urgent tasks as needed. to perform more urgent tasks as soon as they are needed.
Incremental Rendering: By splitting work into a series of small tasks, React can step through the entire rendering process in this way, rather than doing it all at once. This allows important updates, such as animation frames, to be prioritized, which improves application responsiveness and performance.
Better Error Handling:Fiber
allowsReact
to “catch” errors in subtrees in the component tree and up-throw them to higher error bounded (Error Boundary
) components.
data structure
The data structure is roughly as follows:
export const Fiber = {
tag: WorkTag,
key: null | string,
elementType: any,
type: any,
stateNode: any,
return: Fiber | null,
child: Fiber | null,
sibling: Fiber | null,
index: number,
...
...
}
Structures in memory
Definitions in the source code
function FiberRootNode(
containerInfo,
tag,
hydrate,
identifierPrefix,
onRecoverableError,
) {
this.tag = tag;
this.containerInfo = containerInfo;
this.pendingChildren = null;
this.current = null;
this.pingCache = null;
this.finishedWork = null;
this.timeoutHandle = noTimeout;
this.context = null;
this.pendingContext = null;
this.callbackNode = null;
this.callbackPriority = NoLane;
this.eventTimes = createLaneMap(NoLanes);
this.expirationTimes = createLaneMap(NoTimestamp);
this.pendingLanes = NoLanes;
this.suspendedLanes = NoLanes;
this.pingedLanes = NoLanes;
this.expiredLanes = NoLanes;
this.mutableReadLanes = NoLanes;
this.finishedLanes = NoLanes;
this.entangledLanes = NoLanes;
this.entanglements = createLaneMap(NoLanes);
this.identifierPrefix = identifierPrefix;
this.onRecoverableError = onRecoverableError;
}
V. A few questions to explore
1. Why do we need fiber data structures when we have reactElement data structures?
ReactElement
is used to describe the UI andfiber
is used to optimize React’s rendering process to perform more efficient updates and task scheduling.
Consider thatReactElement
is still a macroscopic description of the component tree, while Fiber is an engine that works at the micro level
2. Why not just extend ReactElement?
Extending the React Element data structure to support interruptible rendering and task scheduling (i.e., implementing the functionality of Fiber) presents several problems:
Separation of Duties: The React Element is essentially a static description of the user interface, which is relatively simple. It should be kept lightweight and immutable to keep the underlying functionality of React clean and efficient. fiber, on the contrary, is responsible for handling dynamic operations such as state management, task scheduling, prioritization, and so on during rendering. These operations belong to the internal mechanisms of the React framework and are a different domain than the specific description of components (the responsibility of the React Element). Putting this complexity on the React Element would significantly increase the complexity and difficulty of maintaining this data structure.
Backward compatibility: React was designed with backward compatibility in mind. Many existing applications rely on the current React Element representation and behavior. Changing the structure or behavior of a React Element in a significant way can cause extensive compatibility issues, forcing existing applications to undergo extensive refactoring.
Rendering Performance: React Element serves as a declarative description of the UI, and they are created and compared in large numbers. If the dynamic behavior of rendering is incorporated into a React Element, its performance may be negatively impacted by the added complexity. The Fiber structure optimizes this process, resulting in improved performance.
Clear layer of abstraction: One of React’s design philosophies is to provide a simple API and hide complex implementation details. Developers use React Element to define their components without having to worry about how React does task scheduling and state updates internally. Introducing Fiber as a separate internal mechanism allows React to maintain a clean external API while having the power needed to handle complex scenarios.
Specialization: while a React Element describes what the UI looks like, a Fiber node contains not only the UI description, but also additional information needed to perform the update (e.g., current lifecycle state, pending priority updates, etc.) Fiber nodes are richer in information and are better suited to handling the update logic inside the React framework.
And fiber
also needs to know what kind of UI needs to be drawn, here it just separates the UI from the drawing and task scheduling, and Fiber
doesn’t create a new data structure internally that overlaps with ReactElement
‘s functionality. Instead, it uses the existing ReactElement
to understand the application’s component tree and how to render UI
.