This is the 11th day of my participation in the August More Text Challenge. For details, see:August is more challenging
In the previous section we have analyzed the key process from construction to rendering of the Fiber tree. In this section we take a look at the fiber object and consider how a specific fiber node affects the final render.
Reviewing the fiber data structure and the previous interpretation of the fiber tree structure series, we notice that among the fiber attributes, two types of attributes are critical:
-
Fiber node’s own state: In the renderRootSync[Concurrent] phase, it provides certain input data to the child node and directly affects the generation of the child node.
-
Side effects of the fiber node: During the commitRoot phase, if fiber is marked with side effects, the side effect related functions are called (synchronous/asynchronous).
export type Fiber = {|
// 1. The fiber node is related to its own state
pendingProps: any,
memoizedProps: any,
updateQueue: mixed,
memoizedState: any,
// 2. The fiber node is related to the Effect
flags: Flags,
subtreeFlags: Flags, // V17.0.2 is disabled
deletions: Array<Fiber> | null.// V17.0.2 is disabled
nextEffect: Fiber | null.firstEffect: Fiber | null.lastEffect: Fiber | null|};Copy the code
state
There are four attributes associated with the state:
fiber.pendingProps
: Input properties fromReactElement
Object passed in. It andfiber.memoizedProps
The comparison shows whether the attribute has changed.fiber.memoizedProps
: property used the last time the child nodes were generated and kept in memory after generation. Before the generation of child nodes down is calledpendingProps
After the child nodes are generated, thependingProps
Assigned tomemoizedProps
For the next comparison.pendingProps
andmemoizedProps
The comparison shows whether the attribute has changed.fiber.updateQueue
: storageUpdate Update object
Each time an update is initiated, you need to create one on this queueThe update object
.fiber.memoizedState
: Local state in memory since the last generation of child nodes.
Their functions are limited to the fiber tree construction stage and directly affect the generation of child nodes.
Side effects
There are four attributes associated with side effects:
fiber.flags
: Indicates the flag bitfiber
Nodes have side effects (defined in V17.0.2)28 side effects).fiber.nextEffect
: One-way linked list, pointing to the next side effectfiber
Node.fiber.firstEffect
: One-way linked list, pointing to the first side effectfiber
Node.fiber.lastEffect
: One-way linked list, pointing to the last side effectfiber
Node.
As we know from the previous fiber tree construction, the side effects queue of a single fiber node will eventually move up to the root node. So react provides three ways to handle side effects during the commitRoot phase (see Fiber Tree rendering).
In addition, the design of side effects can be understood as complementing the lack of state functionality.
state
Is astatic
Which can only provide data sources for child nodes.- while
Side effects
Is adynamic
Function, as it is called whenFiber tree rendering phase
So it has more power and can be easily acquiredSnapshot before mutation, DOM node after mutation, etc
.even throughCall API
Launch a new roundFiber tree structure
And change even morestate
, causing moreSide effects
.
External API
These two types of properties of the fiber object can affect the render results, but the fiber structure is always a kernel structure, which is invisible to the outside world, and the caller does not even need to know that the fiber structure exists. Therefore, it is normal to modify these two types of properties directly or indirectly by exposing the API.
From the API exposed in the React package, there are only two types of components that support modification:
The purpose of using the API in this section is to modify the state and side effects of fiber, which in turn can change the overall rendering result. This section first introduces the connection between API and state and side effects. The specific implementation of API will be analyzed in detail in the class Component and Hook principles section.
The class components
class App extends React.Component {
constructor() {
this.state = {
// Initial state
a: 1}; } changeState =() = > {
this.setState({ a: + +this.state.a }); // Enter the Reconciler process
};
// Life cycle function: state dependent
static getDerivedStateFromProps(nextProps, prevState) {
console.log('getDerivedStateFromProps');
return prevState;
}
// Life cycle function: state dependent
shouldComponentUpdate(newProps, newState, nextContext) {
console.log('shouldComponentUpdate');
return true;
}
Function: / / life cycle side effects related to fiber. The flags | = Update
componentDidMount() {
console.log('componentDidMount');
}
Function: / / life cycle side effects related to fiber. The flags | = the Snapshot
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('getSnapshotBeforeUpdate');
}
Function: / / life cycle side effects related to fiber. The flags | = Update
componentDidUpdate() {
console.log('componentDidUpdate');
}
render() {
// Return the subordinate ReactElement object
return <button onClick={this.changeState}>{this.state.a}</button>; }}Copy the code
-
State related: Fiber tree construction phase.
- Constructor:
constructor
When instantiated, you can set the initial state and execute it only once. - Life cycle:
getDerivedStateFromProps
inFiber tree structure
Phase (renderRootSync[Concurrent]
), you can modify the state(link). - Life cycle:
shouldComponentUpdate
In,Fiber tree structure
Phase (renderRootSync[Concurrent]
The return value determines whether to execute render(link).
- Constructor:
-
Side effects related: Fiber tree rendering stage.
- Life cycle:
getSnapshotBeforeUpdate
inFiber tree rendering
Phase (commitRoot->commitBeforeMutationEffects->commitBeforeMutationEffectOnFiber
) (link). - Life cycle:
componentDidMount
inFiber tree rendering
Phase (commitRoot->commitLayoutEffects->commitLayoutEffectOnFiber
) (link). - Life cycle:
componentDidUpdate
inFiber tree rendering
Phase (commitRoot->commitLayoutEffects->commitLayoutEffectOnFiber
) (link).
- Life cycle:
As you can see, the class component lifecycle functions provided by the official API are actually provided around the fiber tree construction and fiber tree rendering.
The function components
Note: The main difference between a function component and a class component is that a class component instantiates an instance so it has its own local state. The function component is not instantiated. It is called directly, so it cannot maintain an independent local state. It can only be implemented indirectly by Hook objects (for more details on implementing hooks, see Hook principles).
Fourteen kinds of hooks are defined in V17.0.2, among which the most commonly used ones are useState, useEffect, useLayoutEffect, etc
function App() {
// State related: initial state
const [a, setA] = useState(1);
const changeState = () = > {
setA(++a); // Enter the Reconciler process
};
/ / side effects: fiber. The flags | = Update | Passive;
useEffect(() = > {
console.log(`useEffect`); } []);/ / side effects: fiber. The flags | = Update;
useLayoutEffect(() = > {
console.log(`useLayoutEffect`); } []);// Return the subordinate ReactElement object
return <button onClick={changeState}>{a}</button>;
}
Copy the code
- Status related:
Fiber tree structure
Phase.useState
inFiber tree structure
Phase (renderRootSync[Concurrent]
) can be modifiedHook.memoizedState
.
- Side effects related:
Fiber tree rendering
Phase.useEffect
inFiber tree rendering
Phase (commitRoot->commitBeforeMutationEffects->commitBeforeMutationEffectOnFiber
(Note asynchronous execution,link).useLayoutEffect
inFiber tree rendering
Phase (commitRoot->commitLayoutEffects->commitLayoutEffectOnFiber->commitHookEffectListMount
) execute (execute synchronously,link).
Details and pitfalls
Here are 2 details:
useEffect(function(){}, [])
Is the function ofAsynchronous execution, because it goes through the dispatch center (the implementation can be reviewedScheduling principle).useLayoutEffect
andThe Class components
In thecomponentDidMount,componentDidUpdate
It’s equivalent in terms of call timing, because they’re both therecommitRoot->commitLayoutEffects
Function is called.- Myth: Although the official website documentation recommends using standard ones whenever possible
useEffect
To avoid blocking visual updates, so many developers use ituseEffect
To take the place ofcomponentDidMount,componentDidUpdate
It’s not accurate. If the exact analogy is,useLayoutEffect
thanuseEffect
More in line withcomponentDidMount,componentDidUpdate
The definition.
- Myth: Although the official website documentation recommends using standard ones whenever possible
To verify this conclusion, look at the example in CodesandBox.
conclusion
From the fiber perspective, this section summarizes two types of attributes (state and side effects) in the fiber node that can affect the final render result. It also summarizes the common ways that class and function components can directly or indirectly change the fiber property. Finally, from the perspective of fiber tree construction and rendering, the life cycle functions of class are compared with the Hooks functions of function.
Write in the last
This article belongs to the diagram react source code in the state management plate, this series of nearly 20 articles, really in order to understand the React source code, and then improve the architecture and coding ability.
The first draft of the graphic section has been completed and will be updated in August. If there are any errors in the article, we will correct them as soon as possible on Github.