# Component Mount (Straight, Upper Half)

UI updating, in its essential, is data change. React offers a straightforward and intuitive approach to front-end program with all the moving parts converged in the form of states. Code review is also made easier to me as I like to start with data structures for a rough expectation of the functionalities and processing logic. From time to time, I was curious about how React works internally, hence this article.

It never hurts to have a deeper understanding down the stack, as it gives me more freedom when I need a new feature, more confidence when I want to contribute and more comfort when I upgrade.

This section walks through one of the critical paths of React by rendering a simple component, i.e., a <h1>. Other topics (e.g., Composite components rendering, state driven UI updating and components life cycle) will be discussed in the following articles in a similar, actionable manner.

Files used in this section:
isomorphic/React.js: entry point of ReactElement.createElement()

isomorphic/classic/element/ReactElement.js: workhorse of ReactElement.createElement()

renderers/dom/ReactDOM.js: entry point of ReactDOM.render()

renderers/dom/client/ReactMount.js: workhorse of ReactDom.render(); defines mountComponentIntoNode(), entry point of the logic process, and ReactDOMContainerInfo which is used in DOM rendering

renderers/shared/stack/reconciler/instantiateReactComponent.js: create different types of ReactComponents based on element type

renderers/shared/stack/reconciler/ReactReconciler.js: call mountComponent of various ReactXXXComponent

renderers/shared/stack/reconciler/ReactCompositeComponent.js: ReactComponents wrapper of root element; call mountComponent to initiate TopLevelWrapper, and performInitialMount to initiate ReactDOMComponent

renderers/dom/shared/ReactDOMComponent.js: define ReactDOMComponent

Tags used in the call stack:
- function call
= alias
~ indirect function call

As the locations of source code files can not be obviously derived from import statement in the flat module tree, I will use @ to help locating them in the code snippet listings.

This article is based on React 15.6.2.

## From JSX to React.createElement()

I was not consciously aware of using React.createElement(), as the existence of it is masked by JSX from a developer’s point of view.

In compiling time, components defined in JSX is translated by Babel to React.createElement() called with appropriate parameters. For instance, the default App.js shipped with create-react-app:

is compiled to:

which is the real code executed by a browser. The code above shows a definition of a composite component App, in which JSX, a syntax of interweaving HTML tag in JavaScript code (e.g., <div className=”App”></div>), is translated to React.createElement() calls.

On the application level, this component will be rendered:

normally by a JS entry module named “index.js”.

This nested components tree is a bit too complicated to be an ideal start point, so we forget it now and instead look at something easier - that renders a simple HTML element.

the babeled version of the above code is:

The first step does not do much really. It simply constructs an ReactElement instance populated with whatever passed down to the call stack. The outcome data structure is:

The call stack is:

React.createElement(type, config, children) is merely an alias of ReactElement.createElement();

ReactElement.createElement(type, config, children) 1) copies the elements in config to props, 2) copies the children to props.children and 3) copies the type.defaultProps to props;

Then ReactElement(type ,... ,props) copies the type and props as they are to ReactElement and returns the instance.

The fields populated in the newly constructed ReactElement will be used directly by ReactMount.instantiateReactComponent(), which will be explained in detail very soon. Note that the next step will also create a ReactElement object with ReactElement.createElement(), so I will call the ReactElement object of this phase ReactElement[1].

## Render it

_renderSubtreeIntoContainer() - attach TopLevelWrapper to the ReactElement[1]

The purpose of the next step is to wrap the ReactElement[1] with another ReactElement (we call the instance a [2]) and set the ReactElement.type with TopLevelWrapper. The name TopLevelWrapper explains what it does - wrap the top level element of the component tree passed through render():

An important definition here is that of TopLevelWrapper, I type three stars here *** for you to CTL-f, as you might need to come back to this definition later.

Please note that the entity assigned to ReactElement.type is a type (TopLevelWrapper) which will be instantiated in the following rendering steps. (Then ReactElement[1] will be extracted from this.props.child through render().)

The call stack to construct the designated object is as following:

For initial rendering, ReactMount._renderSubtreeIntoContainer() is simpler than it seems to be, in fact, most branches (for UI updating) in this function are skipped. The only line that is effective before the logic processes to next step is

Now that it should be easy to see how the target object of this step is constructed with React.createElement, the function we just examined in the last section.

instantiateReactComponent() - create a ReactCompositeComponent using ReactElement[2]

The purpose of this is step is to create a primitive ReactCompositeComponent for the top level component:

The call stack of this step is:

instantiateReactComponent is the only long function that is worth discussing here. In our context, it checks the ReactElement[2].type (i.e., TopLevelWrapper) and creates a ReactCompositeComponent accordingly.

It is worth noting that new ReactCompositeComponentWrapper() is a direct call of ReactCompositeComponent constructor:

Then the real constructor get called:

We name the object created in this step ReactCompositeComponent[T] (T for top).

After the ReactCompositeComponent object is constructed, the next step is to call batchedMountComponentIntoNode, initialize ReactCompositeComponent[T] and mount it, which will be discussed in detail in the next section.

Files used in this section:

A complete static call hierarchy:

batchedMountComponentIntoNode() does not do much. It simply invokes another function call to mountComponentIntoNode().

For now let’s omit the delicacy of those indirect function calls and just see them as direct ones. I will cover transaction and batched updates in later sections.

## The cross point of the two halves

mountComponentIntoNode() is the cross point of logic that consists of platform agnostic code (in this article referred as “upper half”) and logic that is HTML specific (lower half). All major tasks of this walk-through are also effectively completed within this function (and its sub-calls), from where 1) a ReactDOMComponent is derived from the top level ReactCompositeComponent[T]; 2) the ReactDOMComponent is rendered to a real DOM element, and 3) the element is inserted into the document object.

In which, 1) is still conducted as a high level operation in upper half, while 2), 3) are concrete DOM operations. After 2) completes, we will be able to see the element <h1 style={"color":"blue"}>hello world</h1> rendered on the screen.

For 1), ReactReconciler.mountComponent() is yet another simple function that calls the corresponding mountComponent() of internalInstance passed to it, in this case, ReactCompositeComponent[T].

One special parameter here is ReactDOMContainerInfo, it is constructed at the same time when it is passed down to ReactReconciler.mountComponent():

The result object ReactDOMContainerInfo[ins] will be used by 3).

Here is the end of the corridor that consists of transient functions. Now we move on to the next important stop.

Initialize ReactCompositeComponent[T]

This is where the magic, I mean, the reaction happens

In the previous step only _currentElement of ReactCompositeComponent[T] is populated with a reference to ReactElement[2], which makes the object a little bit dull. But not anymore. This property will in turn be used to trigger a “reaction” within ReactCompositeComponent[T] and transforms (initialize) the object to something more meaningful.

The designated data structure of this step is:

The call stack in action is:

Next let’s look at the ReactCompositeComponent.mountComponent() implementation.

I will not list the implementation for small functions (when they are get called) but give return value directly for the sake of concision.

Running in the context of ReactCompositeComponent[T] (as a member function), this method

1) assigns the parameters directly to the corresponding properties of ReactCompositeComponent[T] and local variables. The interesting one variable here is publicProps. It will be used very soon;

2) extracts TopLevelWrapper from this._currentElement.type, and calls its constructor to create a TopLevelWrapper instance. In this process:

checks if TopLevelWrapper.prototype.isReactComponent is set, and returns true if so; and

calls the TopLevelWrapper constructor if true is the result of the previous function. I will name the instance TopLevelWrapper[ins] this time.;

This is the time you may want to check the definition of TopLevelWrapper, search for ***.

3) initializes the TopLevelWrapper[ins].props of the new instance with the information stored previously in the wrapper element ReactElement[2] through the publicProps in 1);

4) creates a doubly link between this (ReactCompositeComponent[T]) and TopLevelWrapper[ins]. One link is created using this._instance, another is made with ReactInstanceMap. this._instance will be used very soon in the next step, and ReactInstanceMap will be used in later sections.

I type 4 stars **** here as you might need to come back to check ReactInstanceMap‘s origin.

5) goes to the next step.

Create a ReactDOMComponent from ReactElement[1]

This step strips the wrapper and creates a ReactDOMComponent instance. Plus, we are going to see ReactHostComponent the tirst time. This component is used to chain the function call from the upper half to lower half.

First thing first, the target data structure:

The call stack in action:

ReactCompositeComponent.performInitialMount() does three things. It 1) extracts the ReactElement[1] as mentioned before; 2) instantiates a ReactDOMComponent based on the ReactElement[1].type; and 3) calls ReactDOMComponent.mountComponent() to render a DOM element.

why a performInitialMount is invoked at the end of the mountComponent function? Because it is “initial” for the next mountComponent

Now I give a detailed explanation for each step:

1) this._renderValidatedComponent() simply calls TopLevelWrapper.render() so that ReactElement[1] extracted from TopLevelWrapper[T].props.child is assigned to renderedElement.

2) this._instantiateReactComponent() is an alias to _instantiateReactComponent@renderers/shared/stack/reconciler/instantiateReactComponent.js that has been discussed in the last section. However, renderedElement(i.e., ReactElement[1]) is used to create a ReactDOMComponent instance this time…

wait here,

if we look at the implementation of _instantiateReactComponent() again

the createInternalComponent() of ReactHostComponent is got called because ReactElement[1].type is “h1”, which instantiate a genericComponentClass:

but why it has anything to do with ReactDOMComponent?

In fact, the platform specific component ReactDOMComponent is “injected” to ReactHostComponent as genericComponentClass during compiling time. For now we consider link has already been established and injection mechanism will be discussed later sections.

I type *5 here.

The constructor of ReactDOMComponent is very similar to that of ReactCompositeComponent:

We name the returned instance ReactDOMComponent[ins];

3) ReactReconciler.mountComponent() has already been covered, it simply calls the mountComponent() of the first parameter, in this case, ReactDOMComponent[ins].

Now the logic processes to lower half.

# Component Mount (Straight, Lower Half)

We completed the platform agnostic logic (a.k.a., upper half) that embeds ReactElement[1] into ReactCompositeComponent[T] and then uses it to derive ReactDOMComponent[ins].

This time I will discuss how a renderable HTML DOM element is created with ReactDOMComponent[ins], and complete the JSX-to-UI process.

Files used in this section:

renderers/dom/shared/ReactDOMComponent.js: creates the renderable h1 DOM element

renderers/dom/client/utils/DOMLazyTree.js: adds the h1 to the DOM tree

renderers/dom/client/ReactMount.js: the cross point revisited by the above two actions

## Create the DOM element with document.createElement()

It calls HTML DOM APIs and hits the bottom.

The designated data structure:

The call stack in action:

ReactDOMComponent.mountComponent() is a fairly long and complex function. So I dye the required fields for easily back tracing their origins. Next we look at how exactly it is implemented.

1) It initializes some of the ReactDOMComponent[ins]’s properties with the parameters and global variables. Then all the if conditions are passed until

2) The HTML DOM API document.createElement() is called to create an h1 DOM element.

3) ReactDOMComponentTree.precacheNode() is used to create a doubly link between ReactDOMComponent[ins] and h1 DOM element, it links ReactDOMComponent[ins]._hostNode to the h1 DOM element and the element’s internalInstanceKey back to ReactDOMComponent[ins].

4) As a null _hostParent indicates an internal root component, DOMPropertyOperations.setAttributeForRoot() set element.data-reactroot to empty string "", to mark a root element externally.

5) _updateDOMProperties is a complex method. For now we only need to know the method extracts { “color”: “blue” } from ReactDOMComponent[ins]._currentElement.props and attaches it to the DOM’s style attribute. We will come back to this method in more detail when discussing “setState() triggered UI update”. Search for

*6

in this text when you need check when this function is used first time.

6) Instantiates a DOMLazyTree[ins].

7) _createInitialChildren is another complex method. For now we only need to know the method extracts 'hello world' from ReactDOMComponent[ins]._currentElement.children and attaches it to the DOM’s textContent. We will come back to this method in more detail when discussing “composite component rendering”. You can search for

*7

then.

Then DOMLazyTree[ins] is returned all the way back to the cross point discussed in the last section — mountComponentIntoNode().

## Mount the DOM into the container node

First lemme copy back the stack frame from the last section.

Now the implementation:

Despite the seemly complexity, there is only one line that is effective, that calls insertTreeBefore.

Inside this function, the only one line that is effective is:

which is another HTML DOM API that inserts DOMLazyTree[ins].node (i.e., the h1 DOM element) into the #root element, as instructed with the JSX statement in the very beginning :

Here is the big pircure we have so far

In this series I focus on a very primitive operation — h1 component mount, which nonetheless walk through the complete critical-path of the rendering process. I think this quick end-to-end tour can help establishing an initial knowledge base and confidence for further exploring the uncharted areas. I assume it’s gonna be more intricate and intriguing.

Though good effort is made to simulate a real experience that includes a clear goal and a concrete outcome, it is highly recommended to try the full version of the source code by debugging it in Chrome directly.

# Component Mount (Class, Upper Half)

Files used in this section: the same as section I

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

The component named App is similar to what I gave in the beginning of section I, in which we considered it too complex for beginners. But since we have leveled-up a bit, it does not look that daunting anymore.

As mentioned, the component above is rendered using:

Now the babeled code:

Here we consider Component a common base class, as other methods will not be used in this section.

This time we can fast forward the logic that is shared with simple component.

## Create ReactCompositeComponent[T]

top level wrapper

The designated data structure:

This step is almost the same as that in simple component rendering, so I will give a brief description only, it

1) creates ReactElement[1] using ReactElement.createElement(type, config, children) (This time App is passed to type, and config, children are null);

1. creates ReactElement[2] in _renderSubtreeIntoContainer();

2. creates the designated wrapper with instantiateReactComponent().

This is what we covered in {section I}.

Create ReactCompositeComponent[T]

The designated data structure:

The step is the same as well:

1) ReactDOMContainerInfo[ins] represents the container DOM element, document.getElementById(‘root’);

2) TopLevelWrapper is instantiated (TopLevelWrapper[ins]) and is set to ReactCompositeComponent[T]._instance alongside the initialization of other properties;

3) Again, mountComponentIntoNode is the cross point of upper and lower half, within which ReactCompositeComponent[T].mountComponent returns a complete DOMLazyTree that can be used by ReactMount._mountImageIntoNode, a method from lower half.

This is what we covered in the first part of {section I}.

Except for some small differences in regard to argument values, the the top level wrapper related operations are exactly the same as what we discussed in previous sections. After those operations complete, the logic processes to the first ramification that is specific to class component.

Create a ReactCompositeComponent from ReactElement[1]

This step strips the wrapper and creates another ReactCompositeComponent instance to reflect App component.

The designated data structure:

The call stack in action:

The process is very similar to the performInitialMount() in {section I}. The only difference here is that based on ReactElement[1].type, _instantiateReactComponent creates a ReactCompositeComponent for the class component (App) instead of a ReactDOMComponent. To put it briefly:

1) it calls _renderValidatedComponent() which in turn calls TopLevelWrapper.render() to extract ReactElement[1]; 2) it instantiates a ReactCompositeComponent with _instantiateReactComponent (we name the object ReactCompositeComponent[ins]); and 3) it calls ReactCompositeComponent[ins].mountComponent (recursively) through ReactReconciler, and moves on to the next step.

## Create ReactCompositeComponent[ins]

The designated data structure:

The call stack in action:

Same as in ReactCompositeComponent[T].mountComponent() {section I}, the most important task of this step is to instantiate App with ReactCompositeComponent[ins]._currentElement (ReactElement[1]).

The line in the method that does the job is:

in which the constructor of App gets called.

Then (we name it) App[ins] is set to ReactCompositeComponent[ins]._instance and a back-link is also created through ReactInstanceMap.

This is the custom component App instance which responds to your this.setState(…).

Other operations includes: 1) App[ins].props reference ReactElement[1].props; and 2) ReactCompositeComponent[ins]._mountOrder is set to 2 due to the ++ operating on the global variable nextMountID.

It is important to note that App[ins].render() is another App method we define in the beginning. Unlike TopLevelWrapper[ins].render() that returns a concrete ReactElement instance, App[ins].render() relies on React.createElement() at the time when it is invoked. We are going to visit this method soon.

Since this step is very similar to that initializes the ReactCompositeComponent[T] {section I}, we do not further examine the workhorse method (i.e., mountComponent()).

Create a ReactDOMComponent

We are here again:

Before the a ReactDOMComponent (we know that this is the class that handle DOM operations) can be created, the ReactElements defined within App[ins] needs to be extracted. To do so, App[ins].render() is called by the following line (in _renderValidatedComponent()) {section I}

Then App[ins].render() triggers

The cascading calls of React.createElement()

To understand how the ReactElement tree is established, let’s first revisit the App.render() implementation:

In this code snippet I also give the call order of createElement()s which follows a very simple principle: arguments should be resolved (with createElement()) from left to right before a function (of createElement()) gets called.

Then we can examine the creation of each ReactElement {section I}.

creates ReactElement[2]:

; and

creates ReactElement[3]:

(Now the two arguments for 3) are resolved.)

; and

creates ReactElement[4]:

; and

creates ReactElement[5]:

(Now the arguments for 5) are resolved.)

; and

creates ReactElement[6]:

Combined together we got the element tree referenced by renderedElement:

ReactCompositeComponent[ins]._instantiateReactComponent() — Create ReactDOMComponent[6]

The designated data structure:

The element tree created in the last step is used to create the ReactDOMComponent[6] by the following line (within _instantiateReactComponent()) {section I}

Now ReactReconciler.mountComponent() calls the mountComponent() of the ReactDOMComponent[6] and the logic processes to the lower half.

# Component Mount (Class, Lower Half)

Last time we completed the upper half of the class component rendering logic which is 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.

Files used in this section:

renderers/dom/shared/ReactDOMComponent.js: offers the one of the methods that this section 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 section that is relevant to the methods (or logic process) being discussed.

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

In this section, 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 {section II *7} and only a side branch was triggered. This side branch, as well as the entire method will be discussed in detail in this section.

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

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.

## Create the DOM element[6] (prior _createInitialChildren)

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

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

## Create DOM elements[2-5]

Designated data structure:

As mentioned before, this method was used to create the string child node (‘hello world’) in {section II}. We will reuse this side branch in this section 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.

Big picture

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 {section I}

Second, ReactDOMComponent.mountComponent() which initializes the ReactDOMComponents created in the previous step and create the corresponding DOM nodes based on them. {section I} & {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() {section I}, 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() {section I} 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() {section I} 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. {section II}

# Rendering Pass (Transaction)

To some extent, the sophisticated and efficient UI updating is what makes React React. But before we dive into the well-known mechanisms (virtual DOM and diffing algorithm) that empower the UI updating, we need to understand Transaction which transfers the control from the high-level API setState() to those underlying processing logic.

Files used in this section:

renderers/shared/utils/Transaction.js: defines the core Transaction class

renderers/shared/stack/reconciler/ReactDefaultBatchingStrategy.js: defines ReactDefaultBatchingStrategyTransaction and its API wrapper ReactDefaultBatchingStrategy

renderers/shared/stack/reconciler/ReactUpdates.js: defines the enqueueUpdate() that uses ReactDefaultBatchingStrategy; defines flushBatchedUpdates() that is the entry point method of this section; defines ReactUpdatesFlushTransaction, one of the Transaction s we are going to discuss

shared/utils/PooledClass.js: defines PooledClass for enabling instance pooling

renderers/dom/client/ReactReconcileTransaction.js: defines ReactReconcileTransaction, another Transaction we are going to discuss

Unlike the previous sections that start from everyday APIs and move down the call stack. This section will take a bottom up approach.

So firstly, we look at the

## Transaction the core class

The only de facto “public” method of this class is perform that also offers its core functionality:

Besides the invocation of the callback method passed to it as the first argument, perform() simply 1) invokes initializeAll() before the callback and 2) closeAll() after.

Here the errorThrown is used to indicate an exception occurred within method.call(), in which case the logic jump directly to finally block before errorThrown can get a chance to be set to false.

Next we look at the implementation of the two methods that are invoked before and after perform(),

These two methods simply iterate this.transactionWrappers and call their initialize() and close() respectively.

The this.transactionWrappers is initialized in the de fecto constructor of Transaction with this.getTransactionWrappers():

We will see what exactly are those this.transactionWrappers very soon.

The exception handling detail here is a bit interesting. Take initializeAll() as an instance. In the case that an exception occurs within initialize(), a finally block (instead of a catch) processes the initialize() of the rest of this.transactionWrappers (i.e., from i + 1 to transactionWrappers.length-1). Then the exception interrupts the for loop and the entire initializeAll() logic and processes all the way to the finally block within perform(), the initializeAll()’s caller, which effectively skips

in the case of a exceptional initialization. At last, closeAll() is invoked within the same finally block to finalize the transaction.

Now we know what is a Transaction in its essence, but what is it used for? In order to answer this question, we take a Transaction instantiation as an example that is the transactional entry point of UI updating.

ReactDefaultBatchingStrategyTransaction

Firstly ReactDefaultBatchingStrategyTransaction is a subclass of Transaction that implements getTransactionWrappers():

Next, TRANSACTION_WRAPPERS are the source of this.transactionWrappers that offers the pre (initialize()) and post (close()) functions for perform() used in the last section.

1) in the constructor of ReactDefaultBatchingStrategyTransaction the super class Transaction’s constructor gets called, which initializes this.transactionWrappers with FLUSH_BATCHED_UPDATES defined in 2)

2) defines the two wrapper and their respective initialize() and close(), which is used in the Transaction.initializeAll() and Transaction.closeAll() in the loops iterating FLUSH_BATCHED_UPDATES

3) defines ReactDefaultBatchingStrategyTransaction as a singleton.

Last we look at the public API offered by ReactDefaultBatchingStrategy that can be called from the outside world

ReactDefaultBatchingStrategy is injected {section I *5} to ReactUpdates as batchingStrategy. And the ReactDefaultBatchingStrategy.batchedUpdates() is used by ReactUpdates.enqueueUpdate(), the underlying method of the UI updating entry point setState().

Here is a similar recursion trick as we saw in last section.

1) When the method is entered the first time, ReactDefaultBatchingStrategy.isBatchingUpdates is false, which triggers branch {a} that leads to ReactDefaultBatchingStrategy.batchedUpdates();

2) batchedUpdates() sets ReactDefaultBatchingStrategy.isBatchingUpdates to true, and initializes a transaction;

3) the callback argument of batchedUpdates is enqueueUpdate() itself, so enqueueUpdate will be entered again with transaction.perform() straight away. Note that the pre-methods (initialize()) of both wrappers are emptyFunction so nothing happens between the two times invocation of enqueueUpdate();

4) when enqueueUpdate() is entered the second time (within the context of the transaction just initialized), branch {b} is executed;

5) after enqueueUpdate() returned post-method (close()) of FLUSH_BATCHED_UPDATES is called; This is the workhorse method that processes all the dirtyComponents marked in the previous step(s)

*8 we will come back to this FLUSH_BATCHED_UPDATES.close() and ReactUpdates.flushBatchedUpdates() in the next section

6) last, post-method (close()) of RESET_BATCHED_UPDATES is called, which sets ReactDefaultBatchingStrategy.isBatchingUpdates back to false and completes the circle.

It is important to note that any successive calls of enqueueUpdate() between 3) and 6) are supposed to be executed in the context of ReactDefaultBatchingStrategy.isBatchingUpdates:false, meaning, branch {b} will be taken in such case. So it’s like

Next let’s examine the other Transactions which, together with ReactDefaultBatchingStrategyTransaction, outline the UI updating processing logic.

We start with the ReactUpdates.flushBatchedUpdates() {last section *8}.

As mentioned before, it processes all the dirtyComponents by initiating a ReactUpdatesFlushTransaction that will invoke runBatchedUpdates eventually.

## PooledClass - maintain an instance pool

The two uncommon methods getPooled(), release() are inherited from PooledClass, which provides the instance pooling capacity:

a) if there is no allocated instance (in this case, ReactUpdatesFlushTransaction) in the pool, getPooled() creates a new one;

b) if instances exist in the pool, getPooled() simply returned the instance;

c) release() does not release the instance, instead, it simply put the instance back to the pool.

Like any other kinds of pools, the end purpose of this instance pooling is to reduce the overhead of superfluous resource (in this case, memory) allocation and destruction.

Back to our specific case above:

ReactUpdatesFlushTransaction instances are allocated only when the first time the while loop is executed. After that instances can be obtained through getPooled() from the pool directly.

This level of understanding of PooledClass is sufficient for the rest of this section. So feel free to fast travel to the the next section by ctrl-f “ReactUpdatesFlushTransaction”.

Now we look at its implementation:

1) addPoolingTo() is a “public” method that adds the pooling functionality to a class;

2) oneArgumentPooler() is the getPooled() underlying implementation.

Next we look at addPoolingTo()‘s function body:

1) instancePool is the pool;

2) attach DEFAULT_POOLER (a.k.a., oneArgumentPooler) to the getPooled();

3) set poolSize to 10;

4) attach standardReleaser() to the release().

And this is how getPooled() and release() are implemented:

1) corresponds to b), in which

invokes Klass constructor with the designated parameters (copyFieldsFrom) to initialize the pooling enabled class; and

2) corresponds to a); and

3) corresponds to c).

Last, we look at how addPoolingTo() is used from the outside (ReactUpdatesFlushTransaction):

## ReactUpdatesFlushTransaction

1) it is another instantiation of Transaction that overrides the perform() method;

2) instead of calling ReactUpdate.runBatchedUpdates (the callback) directly, the overridden ReactUpdatesFlushTransaction.perform() nest calls another Transaction (ReactReconcileTransaction)’s perform() method and pass method (i.e., ReactUpdate.runBatchedUpdates()) as its callback. Note that ReactReconcileTransaction is also pooling enabled.

3) TRANSACTION_WRAPPERS defines its pre and post-functions:

in which, NESTED_UPDATES‘s initialize() 1.5) stores the number of dirtyComponents; its close() 3) check if the number has changed. If they are different {a} the flushBatchedUpdates() is called to reiterate the process; or {b} it set dirtyComponents.length back to 0, and returns back to the upper level Transaction, ReactDefaultBatchingStrategyTransaction {last section}.

I will not examine the CallbackQueue related operations (in UPDATE_QUEUEING) and will leave them for later articles when discussing component’s life cycle. *9

To recap:

## ReactReconcileTransaction

It is another Transaction and nothing is out of ordinary.

1) Its wrappers are defined in TRANSACTION_WRAPPERS;

2) as mentioned before, this class is pooling enabled.

Next we look at its three wrapper:

The comment is quite clear here:

SELECTION_RESTORATION is for storing the focus state of text fields before the UI updating (initialize()), and it restores the state after (close());

EVENT_SUPPRESSION is for storing the toggle state for enabling event, and disable event temporarily before (initialize()), and it restores the state after UI updating (close()).

Again, I will not examine the CallbackQueue related operations (in ON_DOM_READY_QUEUEING) here and will leave them for later articles when discussing component’s life cycle. *10

It is important to note that ReactReconcileTransaction relies on the default Transaction.perform(). Its callback is the ReactUpdate.runBatchedUpdates which is passed all the way down to this level.

ctrl-f “runBatchedUpdates” to examine its route.

And this ReactUpdate.runBatchedUpdates will lead to the content of my next section.

to recap:

Conclusion

# Rendering Pass (Individual Element)

UI updating, in its essential, is data change. React offers a straightforward and intuitive way to program front-end Apps as most moving parts are converged in the form of states, and most UI tasks can be done with a single

…, I mean, a single method, setState(). In this article, we are going unfold the setState() implementation, and peek inside the diffing algorithm by mutating an individual DOM element.

Firstly Let’s extend an example from {section III}

Compared to the App component used in {section III}, the new version adds style prop to <p> node, and setState()s desc to 'end' and color to 'green' 5 seconds after the component is constructed.

The instantiating of App has been discussed in {section III}.

ctl-f “setState”
In the same article, I also mentioned ReactInstanceMap, a back link (from the external ReactComponent instance) to the internal ReactCompositeComponent[ins], which will be used very soon.

Here I paste the data structure as a reminder.

## Before transactions

We start from the setState() method body:

Yes, setState() is inherited from ReactComponent.

But wait, what is this.updater? isn’t it set to ReactNoopUpdateQueue in the constructor, and is a no-op? In fact, I believe with the understanding of Transaction(s) and instance pooling {section VI}, if you trace back from the aforementioned ReactComponent instantiating {section III}, you will be able to find out the origin of this.updater very easily.

I will leave this question open so we can move faster to the core part —virtual DOM and diffing algorithm

1) this is the method that obtains the internal ReactCompositeComponent[ins] from the back link ReactInstanceMap;

2) attach an array (_pendingStateQueue) to ReactCompositeComponent[ins], and push the changed state {desc:'end',color:'green'} into it;

3) start the Transaction(s) {section V},

The call stack so far:

Here I also paste the transaction related call graph as a reminder.

## In transactions

The first stop after the Transaction(s) are fully initialized is

This time we have one dirtyComponents, ReactCompositeComponent[ins] which is the first parameter of ReactReconciler.performUpdateIfNecessary().

Like most of the other methods in ReactReconciler class, ReactReconciler.performUpdateIfNecessary() will call the component’s same method, ReactCompositeComponent.performUpdateIfNecessary()

it’s like a polymorphism in a more explicit way

It in turn calls ReactCompositeComponent[ins].updateComponent(). Note that _pendingStateQueue is set right before the logic enters the Transaction context.

1) obtain the external ReactComponent instance (App) from ReactCompositeComponent[ins]._instance (Figure 32);

2) merge the partial state in ReactCompositeComponent[ins]._pendingStateQueue ({desc:'end',color:'green'}) and existing states using Object.assign();

3) this is the lifecycle function that is provided to the developers to avoid reconciliation (the following processing logic) from being executed in case setState() does not change the critical states;

Most likely you do not need this function

4) enter the next stop.

It simply sets the App’s state to the newly merged one. And calls this._updateRenderedComponent() which is the entry point of the diffing algorithm.

The call stack so far,

Then the logic processes to the diffing algorithm.

## Virtual DOM Diffing

Before we start examining the Diffing algorithm, we better have a consent about what exactly are virtual DOMs, as the term did not appear in the code base.

Here I paste an image from {section IV} as a reminder:

The ReactElements are the virtual DOMs we are going to agree on. {section III, section IV} also discussed how the virtual DOM tree are initially established.

In MVC terms ReactElements are modals which contain only data. On the other hand, ReactDOMComponents are controllers that offer actionable methods.

The figure above gives the old virtual DOM tree that is generated in {section III}.

ctl-f “in _renderValidatedComponent()”

This step will generate a new one with ReactCompositeComponent[ins]._renderValidatedComponent() based on the changed states, for the purpose of diffing.

1) obtain ReactDOMComponent[6] through ReactCompositeComponent[ins] (Figure 34);

2) cascading call of React.createElement() in App[ins].render() to create the new DOM tree {section III}, in which the only different DOM node is:

3) the first comparison of diffing algorithm is between types of the old and new root elements;

4) if they are not the same, build the new tree from scratch — the component mounting process is similar to that discussed in {post five};

whenever the root elements have different types, React will tear down the old tree and build the new tree from scratch

5) if the a the same so, start the DOM updating process.

1) get the props from the old virtual DOM (lastProps) and the newly created one (nextProps);

2) ReactDOMComponent._updateDOMProperties() checks the old and new versions of a DOM’s props, and calls CSSPropertyOperations.setValueForStyles() to update the DOM if different;

3) ReactDOMComponent._updateDOMChildren() checks the old and new versions of a DOM’s content (text, inner HTML), and calls ReactDOMComponent.updateTextContent() to update the DOM’s (text) content if different.

The static call stack,

By observing the static call stack, it is not hard to deduce the how the recursion works.

1) one iteration of this recursion updates the properties of one virtual DOM;

2) ReactDOMComponent.updateDOMChildren() is also responsible to go through the current virtual DOM’s direct children and invoke the next iteration for each of them.

note that sub DOM recursing is not the focus of this section

I collapse some method calls in the above call stack,

and draw the call stack in action for clarity:

ReactDOMComponent._updateDOMProperties() —check if a DOM changed

This is the overlooked method in {section II *6}
In this article we focus on only STYLE updating related code.

1) if the new props do not contain “style” at all,

mark all the existing style entries as ‘remove’, note that existing styles are stored in this._previousStyleCopy in step 2);

2) copy nextProp (current styles) to this._previousStyleCopy;

3) if there are existing styles,

update by a) marking existing style entries that are not in nextProp as ‘remove’ and b) marking style entries in nextProp as ‘add’ if it is different from the existing entry on the same key;

4) if not, simply mark all the styles in nextProp as ‘add’;

5) conduct the real DOM operations. Note that getNode() is an alias to ReactDOMComponentTree.getNodeFromInstance() that uses ReactDOMComponent._hostNode to get the associated DOM element {section II}.

ctl-f “ReactDOMComponent[ins]._hostNode”

CSSPropertyOperations.setValueForStyles() — update props

Here the only line that is applicable here is style[styleName] = styleValue; that set the node.style with styles marked in the previous method.

As a result, Node.style[‘color’] = ‘red’.

_updateDOMChildren —check if a DOM’s content changed (and recurse its children)

We omit the dangerouslySetInnerHTML related code and focus only on hot paths

The only line that is applicable here is

ReactDOMComponent.updateTextContent() — update content

Presumably ReactDOMComponent.updateTextContent() is used to set the text from 'start' to 'end'. But the call stack of this process is a bit too deep for this simple operation,

Here ReactComponentBrowserEnvironment is injected as ReactComponentEnvironment.

The ReactDOMComponentTree.getNodeFromInstance() method is discussed in the previous section.

As expected, the last card in this stack is setTextContent() which sets Node.textContent directly. This method is covered in {section IV} so I will not repeat its implementation.

The sub call stack of ReactDOMComponent.updateTextContent() and the ‘end’ result of it:

In the next section we are going to further investigate the diffing algorithm by observing the mutation of DOM trees, which also concludes this series (for a period of time). I hope you will feel more

next time when using setState().

# Rendering Pass (Element Tree)

Next let’s use two examples to examine the diffing algorithm more in depth. More specific, we look at how the algorithm deals with a mutating DOM tree.

N.b., the examples used in this article are derived from the official document which also provides a high level description of the diffing algorithm. You might want to read it first if the topic does not seem very familiar.

Example 1., diffing of key-less nodes

the babeled version of render(),

## The old & new virtual DOM tree

We know the result virtual DOM tree of the render() method is {section III} (nested calling of React.createElement())

We ignore the ReactElement’s corresponding controllers (i.e., ReactDOMComponent) for simplicity.

The figure above gives the old virtual DOM tree that is generated by the initial rendering. As in {last post}, a setState() is fired after 5 seconds, which initiates the updating process,

With this data structure in mind, we skip the logic process (mostly, before transaction) that is identical to {last post}, and move directly to the diffing algorithm,

The steps 1–5) are also identical to {last post}.

, which starts by creating the new DOM tree (Figure 38) with ReactCompositeComponent._renderValidatedComponent(). {section III}

Root nodes are the identical, so “diff” their direct children

Since the types of ReactElement[1] are the same (“ul”), the logic goes to 5) as in {last post}.

in {last post} step 1) updates a DOM node properties; and 2) updates its content.

But for the the root node (ReactElement[1]) the only purpose of the whole ReactDOMComponent.updateComponent() method call is to recurse and update ReactElement[1]’s direct children because neither the node’s properties and its content are changed.

I also extend the static call stack from {last post} as a lead:

As mentioned before, the recursing starts from ReactDOMComponent._updateDOMChildren(). In the following sections, we will follow the hierarchy, one function a time, and go for the bottom of the stack.

## Recursing children elements

I fold up the content updating related code so we can focus on DOM children recursing

1) remove the children only when necessary (lastChildren != null && nextChildren == null);

2) start the recursing.

ReactMultiChild.updateChildren() I — The actual work horse

After the methods that are either alias or those with very little (preprocessing) operations, we come to the work horse that I) recurses virtual DOM children, compares the new/old versions of them and modifies ReactDOMComponent’s accordingly (we name them virtual DOM operations for simplicity); and II) commits the operations to real DOMs.

the role of this ReactMultiChild.updateChildren() is similar to that of mountComponentIntoNode() in initial rendering {section I}

We firstly look at the virtual DOM operations, I). Note that the two input parameters of the responsible method ReactDOMComponent._reconcilerUpdateChildren() are i) prevChildren, i.e., ReactDOMComponent._renderedChildren which is set to an object of its sub-ReactDOMComponents in initial rendering {section IV}; and ii) nextNestedChildrenElements, i.e., nextProps.children passed from ReactDOMComponent._updateDOMChildren().

ReactDOMComponent._reconcilerUpdateChildren() — Virtual DOM operations

Before 2) the virtual DOM can be traversed and compared, this method 1) calls

flattenChildren() — converts ReactElement array into an object (map)

Here we need to pay attention to the callback passed to traverseAllChildren()

, which set individual ReactElement with its associated key (name) in an object (map). Next we look at the traverseAllChildren() method body, to see in particular how the keys are generated.

We have described this method in {section IV},

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), invokes the aforementioned callback that…

“set individual ReactElement with its associated key (name) in an object” as mentioned soon before.

The keys are generated with getComponentKey(),

which basically uses the index of the array as the key in the object (index.toString(36)), in the case that the key is not explicitly set in “key-less nodes”.

The static (sub) call stack of flattenChildren(),

now we have an key-value object nextChildren to be “diffed” with prevChildren.

ReactChildReconciler.updateChildren() — manipulate the virtual DOM tree

updating is nothing more than modifying, adding, and deleting

This method traverse the nextChildren, and

1) recurse back to ReactReconciler.receiveComponent() to modify the content of the associated DOM nodes as in {last post} if the types of the corresponding “pre” and “next” nodes are the same (judged by shouldUpdateReactComponent() {last post}), the logic branch of which applies to

and

as the comparison is based on the counterparts’ index (that is also key);

2) re-mount the virtual DOM if types of “pre” and “next” nodes are different, or the corresponding “pre” node simply does not exist;

As in {section IV}, the virtual DOM’s corresponding li node has been created in the mounting process;

3) un-mount “pre” virtual DOM(s) if they do not exist in the “next” ones.

The content updating operations are encapsulated in the recursion of ReactReconciler.receiveComponent() {last post}, whilst the operations on real DOM tree are conducted when the logic processes back in ReactMultiChild.updateChildren().

ReactMultiChild.updateChildren() II — matipulate real DOMs

This logic block iterates the nextChildren, and when necessary, it

III) mark that a node’s position has changed;

IV) mark a newly added node;

V) mark a removed node;

VI) commit the changes to the DOM tree {last post}

The branch applies here is IV) that adds the ReactElement[4] associated node to the DOM tree.

And in VI)

So the last card in this stack is DOMLazyTree.insertTreeBefore(). We already know from {section II} that this method calls the HTML DOM API

So what happens when

## Diffing nodes with keys

Example 2.

The process logic are the same as in key-less nodes before ReactDOMComponent.flattenChildren(), in which the designated keys instead of the array index will be used to establish the key-value object,

So in ReactChildReconciler.updateChildren() the comparison of the two virtual DOM trees can be better aligned,

and the recursive ReactReconciler.receiveComponent() does not incur any DOM operations by comparing nodes (key: one and two) with same content , and only the necessary DOM operation, i.e.,

is conducted for the node (key: new) in ReactMultiChild.updateChildren().

As a result, keys can spare some unnecessary DOM operations for mutating a DOM tree .

The above code also changes the DOM tree structure. Can you answer why the keys are not required here?

—End note—

Reading source code with a purpose is like searching an array, in which, theoretically, it is O(n) - O(log n) faster when the array has already been sorted. This series aims to sort out the React code base for you, so you will be able to enjoy the O(log n)` whenever having a purpose(s).