When to use React.memo() over useMemo() & vice-versa ?
Last Updated :
22 Mar, 2024
React provides us with powerful tools to optimize the performance of our applications. Two such tools are `React.memo()` and `useMemo()`, which serve similar yet distinct purposes.
In this article, we’ll explore when to use `React.memo()` over `useMemo()` and vice versa, along with syntax and code examples to illustrate their usage.
React.memo():
`React.memo()` is a higher-order component (HOC) provided by React. It’s used to memoize the rendering of functional components based on their props. This means that React will re-render the component only if its props have changed since the last render.
Syntax of React.memo():
const MemoizedComponent = React.memo((props) => {
// Component logic here
});
useMemo():
`useMemo()` is a React hook used to memoize the result of expensive computations within functional components. It accepts a function and an array of dependencies. The result of the function is memoized until one of the dependencies changes.
Syntax of useMemo:
const memoizedValue = useMemo(() => {
// Expensive computation
}, [dependency1, dependency2, ...]);
Choosing Between React.memo() and useMemo():
Feature
| React.memo( )
| useMemo( )
|
---|
Purpose
| Used to memoize components.
| Used to memoize values.
|
---|
Usage
| Wraps a React component, preventing re-renders if props have not changed.
| Called inside a React component to memoize expensive calculations.
|
---|
Type of Memoization
| Shallow comparison of props by default, but can accept a custom comparison function.
| Memoizes any calculated value, including objects, arrays, and other data types.
|
---|
When to Use
| When a component frequently re-renders with the same props.
| To optimize performance by avoiding expensive calculations on every render.
|
---|
Scope
| At the component level for preventing re-renders.
| Inside a component to memoize specific values or computations.
|
---|
Example Use Case
| Memoizing a list item component in a large list to prevent unnecessary re-renders of all list items when one item changes.
| Memoizing the result of a filter or sort operation on a list to avoid recalculating the list on every render.
|
---|
Syntax Example
| React.memo(Component)
| const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
|
---|
Example of React.memo() & useMemo:
Example: Below is the example of TodoList with React.memo() based on todos prop to prevent unnecessary re-renders. Use useMemo() for TodoItem to optimize completion status computation based on todo.completed, avoiding redundant recalculations.
Javascript
// src/App.js
import React, { useState } from 'react';
import TodoList from './TodoList';
const App = () => {
const [todos, setTodos] = useState([
{ id: 1, text: 'Learn React', completed: false },
{ id: 2, text: 'Build a Todo App', completed: true },
{ id: 3, text: 'Master React Hooks', completed: false }
]);
const [count, setCount] = useState(0);
const [inputText, setInputText] = useState("");
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ?
{ ...todo, completed: !todo.completed } :
todo
));
};
const handleAdd = () => {
// Create a new todo object with a unique ID
const newTodo = {
id: todos.length + 1,
text: inputText,
completed: false
};
// Update todos state with the new todo
setTodos([...todos, newTodo]);
// Clear input field after adding todo
setInputText("");
};
return (
<div>
<h1>Todo List</h1>
<TodoList todos={todos} />
<button onClick={() => toggleTodo(1)}>
Toggle Todo 1
</button>
<input
type="text"
placeholder='Add todo'
value={inputText}
// Update inputText state
onChange={(e) => setInputText(e.target.value)} />
<button onClick={handleAdd}>Add</button>
<h3>{count}</h3>
<button onClick={
() =>
setCount(count + 1)
}>
Inc
</button>
</div>
);
};
export default App;
Javascript
//src/TodoList.js
import React from 'react';
import TodoItem from './TodoItem';
const TodoList = ({ todos }) => {
console.log('TodoList rendered');
return (
<div>
{todos.map(todo => (
<TodoItem key={todo.id} todo={todo} />
))}
</div>
);
};
export default React.memo(TodoList);
Javascript
// src/TodoItem.js
import React, { useMemo } from 'react';
const TodoItem = ({ todo }) => {
const completed = useMemo(() => {
console.log(
`Computing completion
status for todo "${todo.text}"`
);
console.log(
`This is only called for
the todo which is changed`
);
return todo.completed ?
'Completed' :
'Incomplete';
}, [todo]);
return (
<div>
<input type="checkbox"
checked={todo.completed} readOnly />
<span>{todo.text}</span>
<span>({completed})</span>
</div>
);
};
export default TodoItem;
Output:
Output for Todo
Share your thoughts in the comments
Please Login to comment...