Utilizing React.memo
helps optimize performance by skipping the re-rendering of a component if its props have not changed.
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:
JavaScript
x
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:
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.
JavaScript
const TaskList = ({ tasks }) => {
console.log("child render");
return (
<>
<h2>Task List</h2>
{tasks.map((task, idx) => (
<p key={idx}>{task}</p>
))}
</>
);
};
export default TaskList;
Solution
To resolve this issue, we can use React.memo
. Wrapping the TaskList
component in React.memo
prevents unnecessary re-renders.
index.js
JavaScript
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:
JavaScript
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);