React Memo

Utilizing React.memo helps optimize performance by skipping the re-rendering of a component if its props have not changed.



Performance Optimization

By avoiding unnecessary re-renders, React.memo can boost your application’s performance.




Problem

Consider this example where the TaskList component re-renders even if the tasks haven’t changed.

index.js:

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

const App = () => {
  const [counter, setCounter] = useState(0);
  const [tasks, setTasks] = useState(["task 1", "task 2"]);

  const incrementCounter = () => {
    setCounter((prevCounter) => prevCounter + 1);
  };

  return (
    <>
      <TaskList tasks={tasks} />
      <hr />
      <div>
        Counter: {counter}
        <button onClick={incrementCounter}>+</button>
      </div>
    </>
  );
};

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

TaskList.js:

const TaskList = ({ tasks }) => {
  console.log("child render");
  return (
    <>
      <h2>Task List</h2>
      {tasks.map((task, idx) => (
        <p key={idx}>{task}</p>
      ))}
    </>
  );
};

export default TaskList;

In this setup, clicking the increment button triggers a re-render of the TaskList component, even though the tasks haven’t changed. If this component were more complex, it could negatively affect performance.




Solution

To resolve this issue, we can use React.memo. Wrapping the TaskList component in React.memo prevents unnecessary re-renders.

index.js:

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

const App = () => {
  const [counter, setCounter] = useState(0);
  const [tasks, setTasks] = useState(["task 1", "task 2"]);

  const incrementCounter = () => {
    setCounter((prevCounter) => prevCounter + 1);
  };

  return (
    <>
      <TaskList tasks={tasks} />
      <hr />
      <div>
        Counter: {counter}
        <button onClick={incrementCounter}>+</button>
      </div>
    </>
  );
};

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

TaskList.js:

import { memo } from "react";

const TaskList = ({ tasks }) => {
  console.log("child render");
  return (
    <>
      <h2>Task List</h2>
      {tasks.map((task, idx) => (
        <p key={idx}>{task}</p>
      ))}
    </>
  );
};

export default memo(TaskList);
Scroll to Top