Curriculum
Course: React
Login

Curriculum

React

Text lesson

React Memo

Using memo allows React to skip rendering a component if its props haven’t changed, which can enhance performance.

This section utilizes React Hooks. For additional details on Hooks, refer to the React Hooks section.

Problem

In this example, the Todos component re-renders even if the todos have not changed.

Example:

index.js:

import { useState } from "react";
import ReactDOM from "react-dom/client";
import Todos from "./Todos";

const App = () => {
 const [count, setCount] = useState(0);
 const [todos, setTodos] = useState(["todo 1", "todo 2"]);

 const increment = () => {
    setCount((c) => c + 1);
 };

 return (
    <>
      <Todos todos={todos} />
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
      </div>
    </>
 );
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

Todos.js:

const Todos = ({ todos }) => {
  console.log("child render");
 return (
    <>
      <h2>My Todos</h2>
      {todos.map((todo, index) => {
        return <p key={index}>{todo}</p>;
      })}
    </>
 );
};

export default Todos;

Clicking the increment button causes the Todos component to re-render. If the component were more complex, this could lead to performance issues.

Solution

To address this, we can use memo to prevent the Todos component from unnecessary re-renders.

Wrap the export of the Todos component in memo as follows:

Example:

index.js:

import { useState } from "react";
import ReactDOM from "react-dom/client";
import Todos from "./Todos";

const App = () => {
 const [count, setCount] = useState(0);
 const [todos, setTodos] = useState(["todo 1", "todo 2"]);

 const increment = () => {
    setCount((c) => c + 1);
 };

 return (
    <>
      <Todos todos={todos} />
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
      </div>
    </>
 );
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

Todos.js:

import { memo } from "react";

const Todos = ({ todos }) => {
  console.log("child render");
 return (
    <>
      <h2>My Todos</h2>
      {todos.map((todo, index) => {
        return <p key={index}>{todo}</p>;
      })}
    </>

 );
};

export default memo(Todos);

Now, the Todos component will only re-render when the todos passed to it via props are updated.