Open In App

When to use React.memo() over useMemo() & vice-versa ?

Last Updated : 22 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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:

Untitled-design-(19)

Output for Todo



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads