# Understanding The React Source Code - Initial Rendering (Simple Component) II

In the last article we went through the process that creates a ReactCompositeComponent instance from JSX expression. This one will continue the walk-through of simple component rendering, from the point of batchedMountComponentIntoNode().

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

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

renderers/shared/stack/reconciler/ReactCompositeComponent.js: call mountComponent to initiate TopLevelWrapper, and performInitialMount to initiate ReactDOMComponent

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

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 articles.

# mountComponentIntoNode() - 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.

# ReactCompositeComponent.mountComponent() - 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 in the previous post, 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 posts.

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

5) goes to the next step.

# ReactCompositeComponent.performInitialMount() - 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 post. 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 posts.

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.

To be continued…

That's it. Did I make a serious mistake? or miss out on anything important? Or you simply like the read. Link me on -- I'd be chuffed to hear your feedback.