When do (and don’t) children re-render in React?

Vardan HakobyanVardan Hakobyan
3 min read

Photo by Ferenc Almasi on Unsplash

When writing React components, we always strive to keep optimization in mind. It’s always useful to know when unnecessary re-rendering occurs in our code, especially if we have heavy components in our app.

So let’s dive in and see what happens with child components when their parents re-render.

In most cases we use child components by their name. Let’s examine the following code:

import { useState } from "react";

const Parent = () => {
  const [number, setNumber] = useState(0);

  console.log('<Parent> renders');

  return (
    <div>
      Number is {number}
      <div>
        <button onClick={() => setNumber(prev => prev + 1)}>
          Increment
        </button>
      </div>
      <Child />
    </div>
  );
};

const Child = () => {
  /* Some time-consuming logic... */

  console.log('<Child> renders');

  return (
    <div>
      <div>Child component</div>
    </div>
  );
};

const App = () => {
  return (
    <Parent />
  );
};

export default App;

Every time the button is pressed, the state of the Parent component changes and it re-renders, which causes re-rendering <Child /> component as well.

How can we prevent unnecessary re-renders for the Child component? Let’s explore two approaches to achieve this

Approach 1: Our friend React.memo

If we wrap the Child component into React.memo, the Parent’s re-render will not cause the Child to re-render.
Quick reminder — React.memo memoizes components, ensuring they are not re-rendered when their props remain unchanged.

import { memo, useState } from "react";

const Parent = () => {
  const [number, setNumber] = useState(0);

  console.log('<Parent> renders');

  return (
    <div>
      Number is {number}
      <div>
        <button onClick={() => setNumber(prev => prev + 1)}>
          Increment
        </button>
      </div>
      <Child />
    </div>
  );
};

const Child = memo(() => {
  /* Some time-consuming logic... */
  console.log('<Child> renders');

  return (
    <div>
      <div>Child component</div>
    </div>
  );
});

const App = () => {
  return (
    <Parent />
  );
};

export default App;

This is, in fact, one of the ways to stop unnecessary re-renders.

Approach 2: Using {children} prop

We can use children prop to achieve the same result. Let’s see it in action.

{children} prop allows the parent component to accept and render its children components dynamically.

import {useState} from "react";

const Parent = ({children}) => {
  const [number, setNumber] = useState(0);

  console.log('<Parent> renders');

  return (<div>
    Number is {number}
    <div>
      <button onClick={() => setNumber(prev => prev + 1)}>
        Increment
      </button>
    </div>
    {children}
  </div>);
};

const Child = () => {
  // Some time-consuming logic
  console.log('<Child> renders');

  return (
    <div>
      <div>Child component</div>
    </div>
  );
};

const App = () => {
  return (
    <Parent>
      <Child />
    </Parent>
  );
};

export default App;

Using children prop here makes the code easier to follow, and also removes extra clutter coming from memo.

While these 2 approaches help us remove unnecessary re-rendering child components, bear in mind that we don’t need to blindly optimize everything. If our component doesn’t involve heavy calculations or other performance bottlenecks, we usually shouldn’t prematurely optimize it. Always strive to keep components small and easy to follow, and optimize them only when necessary.

Thanks for reading! If you have any notes, remarks or questions, please share them in the comments.

Stay updated with the latest JavaScript and software development news! Join my Telegram channel for more insights and discussions: TechSavvy: Frontend & Backend.

0
Subscribe to my newsletter

Read articles from Vardan Hakobyan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Vardan Hakobyan
Vardan Hakobyan

Hi, I'm a seasoned software engineer with a strong focus on JavaScript. I'm passionate about sharing my knowledge and experiences to help others learn something new and avoid the same pitfalls I've encountered along the way.