How react's rendering flow works

Douglas Almeida - Aug 27 - - Dev Community

To create a healthy application, it's important to understand How react's rendering flow works, and what happens when a stage changes.

This topic is quite expensive, but I will try to summarize this topic in a way that you can understand.

Let's start!

Flow stages

The flow basically happens in three stages:

  • Trigger a render
  • React renders your components
  • React commits changes to the dom

Diagram

Let's go through each one.

Have you ever wondered what the meaning of this code is?

Basically, it's the entry point of our application usually meaning main.tsx or index.tsx, this file is responsible for initial rendering, "React will establish a root for the domNode and handle the DOM management within it.

Main file

HTML example

<App /> component is our root component, all our flow needs to go through it, Routes, Providers and etc...

The first rendering will be based on this guy.

Ok, now we know how to work initial render, let's understand when react re-rendering a component.

React will re-rendering a component in three situations:

  • Hooks Changed (useState, Context, useReducer, UseEffect and etc..)
  • Props Changed
  • Parent Component re-rendered

When it happens React will:

  • Recreate HTML of this component
  • Will Compare with the old version
  • If something changes, it will rewrite/commit HTML on the screen (React won't unmount and mount component again, re-render will only modify what changes in the component).

This whole process isn't done directly in real DOM, because it could be
slow and costly in terms of performance, react uses VIRTUAL DOM and the guy responsible for these calculations it's called RECONCILIATION.

Virtual DOM: The Virtual DOM is a lightweight copy of the real DOM used by React. It allows React to efficiently update the UI by comparing the current and previous versions of the Virtual DOM.

Reconciliation/Diffing Algorithm: React compares the current Virtual DOM with the previous one to identify changes (diffs), Based on these differences, React efficiently determines the necessary updates to the real DOM, targeting only the changed parts.

If you install and use React Devtools you will be able to understand the entire process of your component rendering, in the profile you can click on the blue point on the left and it will record for you what's happened with the components.

React Dev Tools1

React Dev Tools2

React Dev Tools3

Let's see one example

I have my root component and a simple Container with a input and Counter Component inside it.

import { Container } from './Container'

const App = () => {
  return (
    <div
      style={{
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center',
        height: '100vh',
      }}
    >
      <Container />
    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode
import { useState } from 'react'
import { Input } from './components/ui/input'
import { Counter } from './Counter'

export const Container = () => {
  const [inputValue, setInputValue] = useState('')

  return (
    <div
      style={{
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center',
        gap: '20px',
        width: '300px',
      }}
    >
      <h1>Root Component</h1>
      <Input
        type="text"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
        style={{
          width: '200px',
        }}
      />
      <span>
        Lorem ipsum dolor sit amet, 
        consectetur adipisicing elit. Ipsum deleniti
        eum eveniet a neque dolores, 
        facilis est consectetur numquam blanditiis
        illum nam tenetur eius expedita laborum? 
        Hic praesentium inventore sunt?
      </span>

      <Counter />
    </div>
  )
}

Enter fullscreen mode Exit fullscreen mode
import { useState } from 'react'
import { Button } from './components/ui/button'

export const Counter = () => {
  const [count, setCount] = useState(0)

  return (
    <div
      style={{
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center',
        gap: '20px',
      }}
    >
      <span>{count}</span>

      <Button
        style={{
          width: '100%',
        }}
        onClick={() => setCount(count + 1)}
      >
        +
      </Button>
      <Button
        style={{
          width: '100%',
        }}
        onClick={() => setCount(count - 1)}
      >
        _
      </Button>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Now let's enable a feature in React dev Tools, with which we can see highlight updates when components are re-rendered.

React DevTool Highlights

In the first case, we'll click on the component button to increase the counter value, as you can see, only it is being re-rendered again.

It happens because in this case, we are just updating the component, every time we click on the increase button, this event handler is called onClick={() => setCount(count + 1)} , and the counter state is updated.

All the steps I explained above take place in this quick process.Now we'll type something in our input within the  Component.

As we can see, the component is being re-rendered because we are updating inputValue state every time we type something in the input, but the component is being re-rendered too, it's happening because Counter is children from Container, and when the parent component is re-rendered, the children are also.

We have some resources in react to avoid this behavior in certain situations, using the memo, but I'll talk about that in another post.

That's all for today guys! I hope you liked the content, leave your feedback.

. .
Terabox Video Player