The version corresponding to this article reactis18.2.0
How is the following domstructure reacttraversed internally?
const App = () => {
return (
< div >
< button > +1 </ button >
< A count = {0} />
</ div >
);
};
const A = ( props ) => {
useEffect ( () => {
console . log (props. count );
}, [props.count ] );
return < div > {props.count} </ div > ;
};
Contents
reactInternal traversal core logic:
- function
renderis called whencommitPassiveUnmountOnFiber commitPassiveUnmountOnFiberhandle differentWorkTagand callrecursivelyTraversePassiveUnmountEffectsrecursivelyTraversePassiveUnmountEffectsDetermine whether to traverse the current child node according to whether the currentFiberchild node haspassive effect(useEffect,, )useLayoutEffectFiber- If there are child nodes
passive effect, traverse the child nodes first (depth first) until the final leaf node is found and exit the current loop. - Then enter the sibling node and start traversing the child nodes of the sibling node
- Specifically which sibling node to start traversing from,
reactselect the parent node of the leaf node that exits the loop, check whether there are any child nodes, and then traverse in a loop
- Specifically which sibling node to start traversing from,
- Until finally all
passive effectnodes with are found
- If there are child nodes
commitPassiveUnmountOnFiber (root. current );
function commitPassiveUnmountOnFiber ( finishedWork ) {
// Omitted to handle different WorkTag
recursivelyTraversePassiveUnmountEffects (finishedWork);
}
function recursivelyTraversePassiveUnmountEffects ( parentFiber ) {
// Other processing is omitted
if (parentFiber. subtreeFlags & PassiveMask ) {
let child = parentFiber. child ;
while (child !== null ) {
commitPassiveUnmountOnFiber (child);child =
child.sibling ;
}
}
}
So domthe traversal logic for this paragraph is:
- First start from the root component
FiberRootNodeand getcurrent- that is to say
FiberRootNode.currentisdiv#rootthis is afiberand itstagis3
- that is to say
- Since
Appthere are subcomponents ofpassive effect, it will enterAppthe component, and itstagis0 AppThe node in the component is<div>,<di >oftagis5<div>There are two child elements below<button>,<A>
- The first thing to traverse
<button>ittagis5 <button>There is only one text node inside, nopassive effect- Therefore,
reactit is no longer traversed (jumps out of the current traversal loop, that is,buttonthis article is no longer traversed)
- Therefore,
- After jumping out of the loop, check the sibling
buttonnodes<A>of<A>tag0 - Since
<A>the node has no child nodespassive effect, it jumps out of the loop and ends the entire traversal.
Summarize
- Traverse starting from the following node
- Are there any subcomponents of the current component?
passive effect - Take depth first
- If
domthere is a function component in the node, thisdomwill be traversed, otherwise it will not be traversed - If there are no
fiberchildren under the current , the entire linked list will not be traversed.fiberpassive effect - These will not be traversed if there are currently
fiberonlydomdom
In general, don’t traverse the components to see fiberif there are passive effect:
- Yes, it will definitely be traversed
- No, the following two situations will be traversed, and other situations will not be traversed.
- is
passive effectthe parent component of - and
passive effectcomponents are siblings
- is
passive effectRefers useEffect,useLayoutEffect
The traversal logic is shown in the figure below
Everything with a green tick in the picture will be traversed, and the red tick is the order of traversal.

