Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@ Will be done with a help of [js-code-to-svg-flowchart tool](https://github.com/B
## Languages
- [Chinese](./stack/languages/chinese/book/Intro.md)
- [Korean](./stack/languages/korean/book/Intro.md)
- [Bulgarian](./stack/languages/bulgarian/book/Intro.md)
105 changes: 54 additions & 51 deletions stack/book/Intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

### Scheme, first look


[![](../images/intro/all-page-stack-reconciler-25-scale.jpg)](../images/intro/all-page-stack-reconciler.svg)

<em>Intro.0 All scheme (clickable)</em>
Expand All @@ -11,17 +10,18 @@ So... have a look. Take your time. Overall it looks complex, but in fact, it des

On first look, you probably noticed many colors in the scheme. Each logic item (shape on the scheme) is highlighted in its parent module's color. For example, `methodA` will be red if it’s called from `moduleB`, which is red. Below is a legend for the modules in the scheme along with the path to each file.

[![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/modules-src-path.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/modules-src-path.svg)
[![](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/modules-src-path.svg)](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/modules-src-path.svg)

<em>Intro.1 Modules colors (clickable)</em>

Let’s put them into a scheme to see the **dependencies between modules**.

[![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/files-scheme.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/files-scheme.svg)
[![](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/files-scheme.svg)](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/files-scheme.svg)

<em>Intro.2 Modules dependencies (clickable)</em>

As you probably know, React is built to **support many environments**.
As you probably know, React is built to **support many environments**.

- Mobile (**ReactNative**)
- Browser (**ReactDOM**)
- Server Rendering
Expand All @@ -30,81 +30,84 @@ As you probably know, React is built to **support many environments**.

As a result, a number of files are actually bigger than it looks in the scheme above. Below is the same scheme with multi-support included.

[![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/modules-per-platform-scheme.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/modules-per-platform-scheme.svg)
[![](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/modules-per-platform-scheme.svg)](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/7c2372e1/stack/images/intro/modules-per-platform-scheme.svg)

<em>Intro.3 Platform dependencies (clickable)</em>

As you can see, some items seem doubled. It shows that they have a separate implementation for each platform. Let’s take something simple like ReactEventListener. Obviously, its implementation will be different for different platforms! Technically, as you can imagine, these platform dependent modules should be somehow injected or connected to the current logic flow and, in fact, there are many such injectors. Because their usage is part of a standard composition pattern, I chose to omit them. Again, for simplicity.

Let’s learn the logic flow for **React DOM** in a **regular browser**. It’s the most used platform and it completely covers all of React’s architecture ideas. So, fair enough!


### Code sample

What is the best way to learn the code of a framework or library? That's right, read and debug the code. Alright, we are going to debug **two processes**: **ReactDOM.render** and **component.setState**, which map on mount and update. Let’s look at the code we can write to start. What do we need? Probably several small components with simple renders, so it will be easier to debug.

```javascript
class ChildCmp extends React.Component {
render() {
return <div> {this.props.childMessage} </div>
}
render() {
return <div> {this.props.childMessage} </div>;
}
}

class ExampleApplication extends React.Component {
constructor(props) {
super(props);
this.state = {message: 'no message'};
}
constructor(props) {
super(props);
this.state = { message: 'no message' };
}

componentWillMount() {
//...
}
componentWillMount() {
//...
}

componentDidMount() {
/* setTimeout(()=> {
componentDidMount() {
/* setTimeout(()=> {
this.setState({ message: 'timeout state message' });
}, 1000); */
}

shouldComponentUpdate(nextProps, nextState, nextContext) {
return true;
}

componentDidUpdate(prevProps, prevState, prevContext) {
//...
}

componentWillReceiveProps(nextProps) {
//...
}

componentWillUnmount() {
//...
}

onClickHandler() {
/* this.setState({ message: 'click state message' }); */
}

render() {
return <div>
<button onClick={this.onClickHandler.bind(this)}> set state button </button>
<ChildCmp childMessage={this.state.message} />
And some text as well!
</div>
}
}

shouldComponentUpdate(nextProps, nextState, nextContext) {
return true;
}

componentDidUpdate(prevProps, prevState, prevContext) {
//...
}

componentWillReceiveProps(nextProps) {
//...
}

componentWillUnmount() {
//...
}

onClickHandler() {
/* this.setState({ message: 'click state message' }); */
}

render() {
return (
<div>
<button onClick={this.onClickHandler.bind(this)}>
{' '}
set state button{' '}
</button>
<ChildCmp childMessage={this.state.message} />
And some text as well!
</div>
);
}
}

ReactDOM.render(
<ExampleApplication hello={'world'} />,
document.getElementById('container'),
function() {}
<ExampleApplication hello={'world'} />,
document.getElementById('container'),
function () {}
);
```

So, we are ready to start. Let’s move on to the first part of the scheme. One by one, we will go through all of it.

[To the next page: Part 0 >>](./Part-0.md)


[Home](../../README.md)
43 changes: 21 additions & 22 deletions stack/book/Part-0.md
Original file line number Diff line number Diff line change
@@ -1,94 +1,93 @@
## Part 0

[![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0.svg)
[![](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0.svg)](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0.svg)

<em>0.0 Part 0 (clickable)</em>

### ReactDOM.render

Alright, let’s start with a call of ReactDOM.render.

The entry point is ReactDom.render. Our app starts rendering into the DOM from here. I created a simple component `<ExampleApplication/>` to debug easier. So, the first thing that happens is **JSX will be transformed into React elements**. They are pretty simple, almost plain objects with a simple structure. They just represent what was returned from the component’s render, nothing more. Some fields should already be familiar to you like props, key, and ref. Property type refers to the markup object described by JSX. So, in our case, it’s class `ExampleApplication`, but it also can be just string `button` for Button tag, etc. Also, during React element creation, React will merge `defaultProps` with `props` (if they were specified) and validate `propTypes`.

Check the source code for more details: `src\isomorphic\classic\element\ReactElement.js`

### ReactMount

You can see the module called `ReactMount` (01). It contains the logic of components mounting. Actually, there is no logic inside `ReactDOM`, it is just an interface to work with `ReactMount`, so when you call `ReactDOM.render` you technically call `ReactMount.render`. What is all that mounting about?

> Mounting is the process of initializing a React component by creating its representative DOM elements and inserting them into a supplied `container`.

At least the comment from the code describes it in that way. Well, what does that really mean? Alright, well imagine the next transformation:


[![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/mounting-scheme-1-small.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/mounting-scheme-1-small.svg)
[![](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/mounting-scheme-1-small.svg)](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/mounting-scheme-1-small.svg)

<em>0.1 JSX to HTML (clickable)</em>

React needs to **transform your component(s) description into HTML** to put it into a document. How do we get it get there? Right, it needs to handle all **props, events listeners, nested components**, and logic. It’s needed to granulate your high-level description (components) to really low-level data (HTML) which can be put into a webpage. That is all that mounting really is.

React needs to **transform your component(s) description into HTML** to put it into a document. How do we get it get there? Right, it needs to handle all **props, events listeners, nested components**, and logic. It’s needed to granulate your high-level description (components) to really low-level data (HTML) which can be put into a webpage. That is all that mounting really is.

[![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/mounting-scheme-1-big.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/mounting-scheme-1-big.svg)
[![](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/mounting-scheme-1-big.svg)](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/mounting-scheme-1-big.svg)

<em>0.1 JSX to HTML, extended (clickable)</em>

Alright, let’s continue. But… it’s interesting fact time! Yes, let’s add some interesting things during our journey, to have more "fun".

> Interesting fact: Ensure that scroll is monitoring (02)
> Interesting fact: Ensure that scroll is monitoring (02)

> Funny thing, during the first rendering of a root component, React initializes scroll listeners and caches scroll values so that the application code can access them without triggering reflows. Actually, due to different browser render implementations, some DOM values are not static, they are calculated each time you use them in the code. Of course, this affects the performance. In fact, it’s only for older browsers, which don’t support `pageX` and `pageY`. Reacts tries to optimize this as well. Nice. As you can see, making a fast tool requires a bunch of techniques to be used, this one with scroll is a good example.
> Funny thing, during the first rendering of a root component, React initializes scroll listeners and caches scroll values so that the application code can access them without triggering reflows. Actually, due to different browser render implementations, some DOM values are not static, they are calculated each time you use them in the code. Of course, this affects the performance. In fact, it’s only for older browsers, which don’t support `pageX` and `pageY`. Reacts tries to optimize this as well. Nice. As you can see, making a fast tool requires a bunch of techniques to be used, this one with scroll is a good example.

### Instantiate React component

Look at the scheme, there is an instance creation by number (03). Well, it's too early to create an instance of `<ExampleApplication />` here. In fact, we instantiate `TopLevelWrapper` (internal React class). Let’s check out the next scheme first.

[![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/jsx-to-vdom.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/jsx-to-vdom.svg)
[![](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/jsx-to-vdom.svg)](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/jsx-to-vdom.svg)

<em>0.3 JSX to VDOM (clickable)</em>

You can see three phases, JSX through React elements will be converted into one of internal React component types: `ReactCompositeComponent` (for our own components), `ReactDOMComponent` (for HTML tags), and `ReactDOMTextComponent` (for text nodes). We will omit `ReactDOMTextComponent` and will just focus on the first two.
You can see three phases, JSX through React elements will be converted into one of internal React component types: `ReactCompositeComponent` (for our own components), `ReactDOMComponent` (for HTML tags), and `ReactDOMTextComponent` (for text nodes). We will omit `ReactDOMTextComponent` and will just focus on the first two.

Internal components? Well, that’s interesting. You’ve already heard about **Virtual DOM**, right? Virtual DOM is a kind of DOM representation which is used by React to not touch the DOM directly during diff computations and so on. It makes React fast! But, in fact, there is no files or classes inside React's source code called ‘Virtual DOM’. That’s funny, right? Well, it’s because V-DOM is just a concept, an approach of how to work with the real DOM. So, some people say that V-DOM items refer to React elements, but in my opinion, it’s not exactly true. I think that Virtual DOM refers to these three classes: `ReactCompositeComponent`, `ReactDOMComponent`, `ReactDOMTextComponent`. And you will see later why.

OK, let’s finish with our instantiating here. We will create an instance of `ReactCompositeComponent`, but, in fact, it’s not because we put `<ExampleApplication/>` in `ReactDOM.render`. React always starts rendering a component's tree from `TopLevelWrapper`. It’s almost an idle wrapper, its `render` (render method of a component) will later return `<ExampleApplication />`, that’s it.
OK, let’s finish with our instantiating here. We will create an instance of `ReactCompositeComponent`, but, in fact, it’s not because we put `<ExampleApplication/>` in `ReactDOM.render`. React always starts rendering a component's tree from `TopLevelWrapper`. It’s almost an idle wrapper, its `render` (render method of a component) will later return `<ExampleApplication />`, that’s it.

```javascript
//src\renderers\dom\client\ReactMount.js#277
TopLevelWrapper.prototype.render = function () {
return this.props.child;
};

```

So, only `TopLevelWrapper` is created, nothing more for now. Moving forward. But... first, an interesting fact!
> Interesting fact: Validate DOM Nesting

> Almost every time nested components are rendering, they are being validated by a dedicated module for HTML validation called `validateDOMNesting`. DOM nesting validation means verification of `child -> parent` tag hierarchy. For example, if a parent tag is `<select>`, the child tag should be only one of the following: `option`, `optgroup`, or `#text`. These rules actually are defined in https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect. You’ve probably already seen this module at work, it populates errors like:
<em> &lt;div&gt; cannot appear as a descendant of &lt;p&gt; </em>.
> Interesting fact: Validate DOM Nesting

> Almost every time nested components are rendering, they are being validated by a dedicated module for HTML validation called `validateDOMNesting`. DOM nesting validation means verification of `child -> parent` tag hierarchy. For example, if a parent tag is `<select>`, the child tag should be only one of the following: `option`, `optgroup`, or `#text`. These rules actually are defined in https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect. You’ve probably already seen this module at work, it populates errors like:
> <em> &lt;div&gt; cannot appear as a descendant of &lt;p&gt; </em>.

### Alright, we’ve finished *Part 0*.
### Alright, we’ve finished _Part 0_.

Let’s recap how we got here. Let's look at the scheme one more time, then remove redundant less important pieces, and it becomes this:

[![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0-A.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0-A.svg)
[![](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0-A.svg)](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0-A.svg)

<em>0.4 Part 0 simplified (clickable)</em>

And we should probably fix spaces and alignment as well:

[![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0-B.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0-B.svg)
[![](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0-B.svg)](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0-B.svg)

<em>0.5 Part 0 simplified & refactored (clickable)</em>

Nice. In fact, that’s all that happens here. So, we can take the essential value from *Part 0* and use it for the final `mounting` scheme:
Nice. In fact, that’s all that happens here. So, we can take the essential value from _Part 0_ and use it for the final `mounting` scheme:

[![](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0-C.svg)](https://rawgit.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0-C.svg)
[![](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0-C.svg)](https://raw.githubusercontent.com/Bogdan-Lyashenko/Under-the-hood-ReactJS/master/stack/images/0/part-0-C.svg)

<em>0.6 Part 0 essential value (clickable)</em>

And then we're done!


[To the next page: Part 1 >>](./Part-1.md)

[<< To the previous page: Intro](./Intro.md)


[Home](../../README.md)
Loading