Simple trick to optimize React

Apr 9, 2022

When using React, efficient rendering is crucial for large scale applications to maintain performance. Here is a simple technique to optimize rendering by using the children prop.

Try clicking the increment button below to see the problem.

import ChildComponent from "./ChildComponent"

export default function ParentComponent() {
  return <ChildComponent />
}

Why this happens

The state count "lags" or pauses between each button click because React re-renders every time count changes. This includes the rendering of the ExpensiveComponent, causing unnecessary re-renders.

The optimization

To fix this, we can update the props in TypeScript (if you're using it) and replace the direct rendering of ExpensiveComponent with the children prop. By doing this, we pass ExpensiveComponent as children instead of rendering it inside the parent directly.

1import { PropsWithChildren } from 'react';
2import { useState } from "react";
3
4export default function ChildComponent({ children }: PropsWithChildren) {
5const [count, setCount] = useState(0);
6 return (
7 <div>
8 <h1>Count: {count}</h1>
9 <button onClick={() => setCount(count + 1)}>Increment</button>
10 {children}
11 </div>
12 );
13}
1import { PropsWithChildren } from 'react';
2import { useState } from "react";
3
4export default function ChildComponent({ children }: PropsWithChildren) {
5const [count, setCount] = useState(0);
6 return (
7 <div>
8 <h1>Count: {count}</h1>
9 <button onClick={() => setCount(count + 1)}>Increment</button>
10 {children}
11 </div>
12 );
13}

Next, import the ExpensiveComponent and pass it in as children. Now the ExpensiveComponent is going to be rendered as children.

1import ChildComponent from "./ChildComponent";
2import { ExpensiveComponent } from "./ExpensiveComponent";
3
4export default function ParentComponent() {
5 return (
6 <ChildComponent>
7 <ExpensiveComponent />
8 </ChildComponent>
9 );
10}
1import ChildComponent from "./ChildComponent";
2import { ExpensiveComponent } from "./ExpensiveComponent";
3
4export default function ParentComponent() {
5 return (
6 <ChildComponent>
7 <ExpensiveComponent />
8 </ChildComponent>
9 );
10}

Why this works

In React, components passed as children do not automatically re-render when the parent component updates its state.

Final Demo

import ChildComponent from "./ChildComponent";
import { ExpensiveComponent } from "./ExpensiveComponent";

export default function ParentComponent() {
  return (
    <ChildComponent>
      <ExpensiveComponent />
    </ChildComponent>
  );
}