Understanding Rendering in React ♻ ⚛️
Tags: react, webdev, javascript, reactnative
Published: 2021-01-31 14:34:20

Hey there! 👋🏼

I'm Mateo Garcia, I co-organize a community in Medellin, Colombia called React Medellin. This year I started a series of posts called 'Coding with Mateo'; My first post was about [6 ways to write a React component](https://dev.to/teo_garcia/6-ways-to-write-a-react-component-ts-included-2k42).

![Coding with Mateo billboard](https://dev-to-uploads.s3.amazonaws.com/i/sowd5c0xwoinpbaxaza4.png)

Today I want to share with you what I have researched for a couple of weeks about how rendering works in React. To begin with, I will say that the concept of rendering in React is a little different from how we know it. Let's find out why.

## Table of Contents
1.[Introduction](#introduction)
2.[VirtualDOM](#virtualdom)
3.[Render](#render)
4.[Reconciliation](#reconciliation)
5.[Commit](#commit)
6.[An example](#example)

### Introduction

You are probably here because you have worked with React, interacted with their APIs, changed the state of your components, and seen the magic happen. However, it is sometimes useful to go into a little more detail about how React does what it does. Performance problems can appear when your React application is continuously re-rendering, the application has scaled considerably and, the components are complex and expensive to represent. That's why `Understanding rendering in React` is something that all of us who use this library should understand.

To understand why React is so fast it is important to know these four concepts:

1. Virtual DOM.
2. Render.
3. Reconciliation.
4. Commit.

Let's get started

## VirtualDOM

The Virtual DOM was a strategy that appeared to solve the modifications or mutations that the DOM suffers when using a web or mobile application. Rendering the entire document tree is too costly as applications become more complex; by mutations, we can understand any change that the DOM can undergo: an insertion/modification/deletion of an element or its properties.

Thus, the Virtual DOM came to represent the DOM tree in memory. Perform calculations using the state and props and finally decide which elements of the actual DOM (the browser one, I mean haha) should be mutated. From the [official React website](https://reactjs.org/docs/faq-internals.html):

> The virtual DOM (VDOM) is a programming concept where an ideal, or “virtual”, representation of a UI is kept in memory and synced with the “real” DOM by a library such as ReactDOM. This process is called reconciliation. 

Initially, I said that the concept we normally know as rendering is different in React, I personally considered rendering as the procedure of synchronizing changes in the DOM. React synchronizes the changes in the DOM through three steps.

![Virtual DOM in a graphic](https://dev-to-uploads.s3.amazonaws.com/i/csjl5onhxu99qhokbfjh.png)

## Render

Rendering is a process that is triggered by a change of state in some component of your application, when a state change occurs React:

![React render phase illustration](https://dev-to-uploads.s3.amazonaws.com/i/9s7jqpadoijq32y5b1eo.png)

- It will collect from the root of your App all the components that requested a re-render because their state or their props changed.
- It will invoke these components
  1. If you use `function components` it will invoke the function itself, something like `Header(props)`.
  2. If you use `class components` it will invoke `YourComponent.render()`.

Even when the process's name is rendering, at this point, the DOM has not been modified or altered, which could be a little tricky if you think as I did, about the meaning of render.
  
Since we normally use `JSX`, the code will be transformed to `React.createElement(...)`. The output of the `createElement` will describe how the application should look like in the next version of the render through the next stage called:

## Reconciliation

Once the re-rendering has happened, React has the context of two versions of the `React.createElement` output, the version executed before the state change occurred, and the version executed after the state has changed. 

![Reconcilier process illustration](https://dev-to-uploads.s3.amazonaws.com/i/5b2efk1nj6yhl83jou5i.png)

At this point two objects are describing the UI, React through a heuristic algorithm of order O(n^3) will be able to determine which elements need to be represented again.

Among technical details the React team tells us some aspects about how React identifies which elements were affected:

1. Elements that changed type must be recreated.

2. Changes within the attributes of an element are replaced, without unmounting the element.

3. Upgrades within the element's children recreate all children

4. Updates within child elements that use `key` as attributes are compared and only new items are represented.

## Commit

After React calculated all the changes that should be made in the application tree, `react-dom` appears for the browser and `react-native` for the mobile platforms, which make the modifications to the browser or mobile app API (finally! 🥳). Synchronously React will clean up the past layout effects, run the new layout effects, then the browser will paint the DOM, after that, React will clean up the past effects and mount the new ones; when I talk about effects I refer to the lifecycles method such as [useLayoutEffect](https://reactjs.org/docs/hooks-reference.html#uselayouteffect) and [useEffect](https://reactjs.org/docs/hooks-reference.html#useeffect).

![Commit phase illustration](https://dev-to-uploads.s3.amazonaws.com/i/9pswc5zt2psdqbgiq8oa.png)

To explain the lifecycles method part a little bit more, I bring to you this wonderful graph that Donavon West and his contributors created. This is the project [repo](https://github.com/donavon/hook-flow), check it out!

![React Hooks lifecycle methods flow](https://dev-to-uploads.s3.amazonaws.com/i/rexqxdys2yzjq7m178ba.png)



Before moving on to the example, it is important to understand that under normal conditions, if a component calls `render`, it will automatically do so for all its children. However it is possible to prevent certain components from being re-rendered under certain special cases, I have in my plans to talk about it, however, you can read about `React.PureComponent`, `React.memo`, `React.useMemo`, and `React.useCallback`.

## Example
Consider the following example.
![Rendering example](https://dev-to-uploads.s3.amazonaws.com/i/hnrnb18jxqolmu2vuffb.png)

Here's the code

```jsx
import * as React from "react";
import { useRenderTimes } from '../../utils';

function getRandomHEX() {
  return `#${Math.floor(Math.random() * 16777215).toString(16)}`;
}

function Header() {
  const [color, setColor] = React.useState("#111");
  const count = useRenderTimes();
  return (
    <header style={{ backgroundColor: color }}>
      <p>Header component has re-rendered {count} times</p>
      <button onClick={() => setColor(getRandomHEX())}>Click</button>
    </header>
  );
}

function Footer() {
  const count = useRenderTimes();
  return (
    <footer>
      <p>Footer component has re-rendered {count} times</p>
    </footer>
  );
}

function App() {
  const count = useRenderTimes();
  return (
    <>
      <Header />
      <main>
        <p>Hey, nice to see you again 👋🏼</p>
        <p>The App component has re-rendered {count} times</p>
      </main>
      <Footer />
    </>
  );
}

export { App };
}
```

`useRenderTimes` is a hook that will allow us to accumulate the number of times a component is re-rendered. I saw it in a [post](https://kentcdodds.com/blog/how-to-optimize-your-context-value) by Kent C Dodds, so thanks!

```tsx
import * as React from 'react';

function useRenderTimes() {
  const renderRef = React.useRef(0);

  React.useEffect(() => {
    renderRef.current = renderRef.current + 1;
  });

  return renderRef.current;
}

export { useRenderTimes };
```

The `<Header />` component has its own state, which will be changing once we start pressing the button. Let's take a look

![Rendering example in the second render](https://dev-to-uploads.s3.amazonaws.com/i/9fwem222jn8vn08ywsin.png)


What just happened here is:

1. An event in the `<Header />` component triggered a state change. A render was scheduled.
2. VirtualDOM started analyzing which components were marked as needing to be re-rendered. Only `<Header />` needed it.
3. Through the reconciliation step, it was identified that the style of the `<header></header>` was changing.
4. Dispatched a commit to DOM.
5. Boom, we see the change of the background color.


### Final thoughts

Although rendering in React is a process that can become complex, we must recognize the excellent work done by the entire React Team to improve the day to day experience in web development. Knowing the deeper parts of a tool can be useful for people who are just starting to discover it, as well as for people who have been using it for a long time and want to understand what was going on behind the scenes.

I want to thank the experts who continually strive to share all the knowledge in the most understandable way possible, some of them are [Mark Erikson](https://blog.isquaredsoftware.com/) and [Kent C Dodds](https://kentcdodds.com/blog/). I leave you the link to their blogs. Each article is a gold mine and needs to be recognized.

If you found this post useful and would like to see more content, you could react to this post, which would make me very happy. If you have any comments or corrections that could improve this post, I would be glad to receive them. Thank you for your time 👋🏼 💙.