We have completed the rendering process of a simple component. This time we are going to explore more ramifications of this process by discussing how a class component (a typical one we might use in everyday development) is rendered.

I use {} to reference the previous post 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 post one, in which we considered it too complex for beginners. But since we have leveled-up a bit, it does not look that daunting anymore.

Initialize ReactCompositeComponent[T]

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.

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 posts. After those operations complete, the logic processes to the first ramification that is specific to class component.

The process is very similar to the performInitialMount() in {post two}. 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.

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] {post two}, we do not further examine the workhorse method (i.e., mountComponent()).

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()) {post two}

123

...renderedElement = this._renderValidatedComponent();...

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.