# Understanding The React Source Code - Initial Rendering (Class Component) V

Last time we completed the upper half of the class component rendering logic which is similar to albeit different from simple component rendering in the following respects: 1) it instantiates one additional ReactCompositeComponent to represent the class component (App); and 2) it calls App.render() that triggers cascading React.createElement()s to establish a ReactElement tree.

This time we are going to explore more branches in lower half by examining how the ReactElements in the tree is transformed to their respective ReactDOMComponents, and eventually, to real DOM objects.

renderers/dom/shared/ReactDOMComponent.js: offers the one of the methods that this post focuses on, _createInitialChildren

renderers/dom/client/utils/setTextContent.js: DOM operation, setting text

renderers/dom/client/utils/DOMLazyTree.js: DOM operation, appending child

renderers/shared/stack/reconciler/ReactMultiChild.js: the intermediate method to traverseAllChildren as well as the other method in focus, mountChildren()

shared/utils/traverseAllChildren.js: method that iterates direct sub ReactElements and instantiates their respective ReactDOMComponents

Notations used in the call stack:
↻ loop
? condition

I use {} to reference the previous post that is relevant to the methods (or logic process) being discussed.

The process discussed in this post occurs majorly within ReactDOMComponent[6].mountComponent(). The major task of this method, that derives a DOM object from ReactDOMComponent[6], is covered in {post three}. This task is numbered as 0) for later reference.

In this post, we are going to address one of the methods that we overlooked on purpose last time, _createInitialChildren which is used for handling the newly introduced ReactElement tree as the class component’s children. It was used in a niche case, a text child, in {post three *7} and only a side branch was triggered. This side branch, as well as the entire method will be discussed in detail in this post.

_createInitialChildren is our protagonist today; please search *7 in post three if you want to check its role in the simple component rendering. The other overlooked method _updateDOMProperties in {post three *6} will be discussed in later articles.

To be more specific, this method 1) transforms ReactElements to their corresponding ReactDOMComonents; 2) (recursively) calls ReactDOMComponent[*].mountComponent() to create the DOM objects; and 3) appends them to the root DOM node that is created in 0).

So firstly let’s recap step 0) in the context of class component.

# ReactDOMComponent[6].mountComponent() (before _createInitialChildren)—create the DOM element[6]

time-saving hint: this paragraph is here to keep the post self-contained, the detail of the ReactDOMComponent creation process has been covered in {post three}

Designated data structure:

Call stack in action:

This step creates a DOM object with ReactDOMComponent[6], and set up its attributes.

To recap: it 1) initializes properties of ReactDOMComponent[6]; 2) creates a div DOM element using document.createElement(); 3) creates a double link between ReactDOMComponent[6] and the DOM object; 4) & 5) set the properties and attributes of the newly created DOM object; and 6) embeds the DOM object in DOMLazyTree[1].

ReactDOMComponent[6] gets its DOM node, its children are next in the line

# ReactDOMComponent[6]._createInitialChildren() —create DOM elements[2-5]

Designated data structure:

As mentioned before, this method was used to create the string child node (‘hello world’) in {post three}. We will reuse this side branch in this post when rendering similar nodes (i.e., [3] and [5]), and we name the branch {1}.

In the case of class component, route {2} is hit when this method is accessed the first time. To be specific, this branch handles the ReactElement tree. As mentioned, it 1) transforms ReactElements to ReactDOMComponents (a), generates DOM nodes with ReactDOMComponents (b), and 2) insert DOM nodes to the root node generated with ReactDOMComponent[6] in last step.

The call hierarchy and iteration is a bit complex from now on, so this time I’ll first establish an overview of the big picture before diving into any detail.

The static call stack:

First we examine the bottom of the (complex) stack that operates on the DOM level (by understanding the end purpose, we can be a bit relieved in facing the complex call graph).

## DOMLazyTree.queueText() and DOMLazyTree.queueChild()

DOMLazyTree.queueText() has only one effective line in this walk-through:

Node.textContent is a DOM standard property that represents, well, text content of a node. Apparently, it is the end purpose of route {1}.

DOMLazyTree.queueChild() has one line as well:

Here Node.appendChild() is yet another DOM standard API that inserts a node to another as child. Apparently, it is the last stop of route {2}.

Now we can replace these two methods with their respective essence line.

## Extrapolate the big picture

To do so, we start from methods that we already know.

First, instantiateReactComponent() which instantiates a ReactDOMComponent from ReactElement (we do not have any “composite” ReactElement in the tree now so all the components being created are ReactDOMComponents), which is also the end of the deeply nested call hierarchy {post two}

Second, ReactDOMComponent.mountComponent() which initializes the ReactDOMComponents created in the previous step and create the corresponding DOM nodes based on them. {post three} & {beginning}

Considering the above two operations an {OG} (operation group), it is now easier to explain how the rest of the ReactElement tree is processed.

Here is a high-level explanation:

1. when outer recursion of ReactDOMComponent.mountComponent() is called for non-leaf node, branch {2} will be taken to trigger {OG} for each of the component’s children;

2. when outer recursion of ReactDOMComponent.mountComponent() is called for leaf node that contains text, branch {1} will be in action, which set node.textContent;

3. when outer recursion of ReactDOMComponent.mountComponent() is called for leaf node that does not contain text, _createInitialChildren() will not be called at all.

Please note that in this process ReactDOMComponent.mountComponent() is used repeatedly to create DOM node for the respective ReactDOMComponent instance, so you might need to check its implementation in the beginning of this text if it is not in your (brain) cache.

It’s time to draw the call stack in action:

In this call stack I omit the deep nested call hierarchy that is used to instantiate the ReactDOMComponent from ReactElement as we are going to examine it next.

## The deep nested loop of instantiateReactComponent()

In particular, we need to pay attention to the arguments to keep track the input & output across the fairly deep and complex chain that enlists recursion and callback.

Starting from inside ReactDOMComponent._createInitialChildren():

Next we look at the implementation of ReactDOMComponent.mountChildren(). As mentioned before, it 1) instantiates all the children of ReactDOMComponents; and 2) initializes those ReactDOMComponent by calling ReactDOMComponent.mountComponent().

2) was referred to as “outer recursion” before and is yet another ReactReconciler.mountComponent() {post two}, so we focus on 1)

which is a direct call of

which is, again, a direct call to traverseAllChildren(). Note that instantiateChild is the callback method which is invoked for each child.

It in turn calls instantiateReactComponent() {post one} directly.

We move on to traverseAllChildren()

yet another direct call to traverseAllChildrenImpl()

After those directly one-line calls of another method, traverseAllChildrenImpl() is the true workhouse. this method was also referred to as “inner recursion” soon before.

The logic of traverseAllChildrenImpl() is quite straight forward: when it is called the first time (and the type of children parameter is array), it calls itself for every ReactElement within the array; when it is called successively (children is ReactElement), it invokes the aforementioned callback that internally relies on instantiateReactComponent() {post one} to transform a ReactElement to an empty and uninitialized ReactDOMComonent.

Note that “inner recursion” works on DIRECT children only while the “outer recursion” traverse the ENTIRE ReactElement tree.

After all the ReactElements are transformed to ReactDOMComonents, the output is returned all the way back to ReactDOMComponent.mountChildren() and complete the circle.

To better understand the full circle, you might need to refer to different pieces of the puzzle back and forth, for example, the beginning of this text where ReactDOMComponent.mountComponent() is discussed; the two DOM operations (Node.appendChild, Node.textContent) that define the stack bottom; the discussion of the big picture; as well as this section.

At last, after all the DOM nodes are generated, the logic returns back to ReactReconciler.mountComponent() and the new node tree is inserted to the designated div container. {post three}

That's it. If you have any suggestions, or you just like the read, , and send me your comments. Thank you for your time and attention. I'll catch you later.