Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. React Dictionary
  3. React.memo()

React.memo()

Since: React 16.8(2019)

React's React.memo is a higher-order component that memoizes a component. Even when the parent component re-renders, child component re-rendering can be skipped if the passed props have not changed.

Syntax

// Basic syntax of React.memo
// 1st argument: the component to memoize
// 2nd argument (optional): a comparison function for props (shallow comparison is used by default)
const MemoizedComponent = React.memo(Component);

// Passing a comparison function
// prevProps: previous props, nextProps: current props
// Return true to skip re-rendering, false to allow re-rendering
const MemoizedComponent = React.memo(Component, (prevProps, nextProps) => {
  return prevProps.value === nextProps.value; // true means no re-render
});

Arguments and Return Value

Argument / Return valueDescription
Component (1st argument)The function component to memoize. Cannot be used with class components.
Comparison function (2nd argument, optional)A function that receives the previous and current props. Returning true skips re-rendering; returning false triggers re-rendering. When omitted, shallow comparison is used.
Return valueThe memoized component, which can be used in JSX just like a regular component.

Sample Code

An example where React.memo prevents product cards from re-rendering unnecessarily while typing in a search form on a page with a product list and search input.

import { useState, useCallback } from 'react';

// Card component displaying one product
// Wrapped with React.memo so it skips re-rendering
// as long as product and onAddToCart have not changed
const ProductCard = React.memo(function ProductCard({ product, onAddToCart }) {
  console.log('ProductCard render:', product.name);

  return (
    <div className="product-card">
      <h3>{product.name}</h3>
      <p>{product.price.toLocaleString()} yen</p>
      {/* Pressing the button calls the onAddToCart callback */}
      <button onClick={() => onAddToCart(product.id)}>
        Add to Cart
      </button>
    </div>
  );
});

// Parent component managing the entire product list
function ProductList() {
  // State for the search keyword (re-renders on each keystroke)
  const [searchText, setSearchText] = useState('');

  // List of product IDs in the cart
  const [cartIds, setCartIds] = useState([]);

  // Product master data (in practice, often fetched from an API)
  const products = [
    { id: 1, name: 'Laptop',   price: 98000 },
    { id: 2, name: 'Mouse',    price: 2500  },
    { id: 3, name: 'Keyboard', price: 7800  },
  ];

  // Fix the callback function reference with useCallback
  // This makes React.memo's shallow comparison judge it as "the same function"
  // Without useCallback, a new function is generated every time, making React.memo ineffective
  const handleAddToCart = useCallback(function(id) {
    setCartIds(function(prev) { return prev.concat(id); });
  }, []); // Empty dependency array means the function reference is created only once

  return (
    <div>
      {/* Search form. ProductList re-renders on each keystroke */}
      <input
        type="text"
        placeholder="Search products…"
        value={searchText}
        onChange={function(e) { setSearchText(e.target.value); }}
      />

      {/* Display only products matching searchText */}
      {products
        .filter(function(p) { return p.name.includes(searchText); })
        .map(function(p) {
          return (
            // ProductCard does not re-render if product and onAddToCart have not changed
            <ProductCard
              key={p.id}
              product={p}
              onAddToCart={handleAddToCart}
            />
          );
        })
      }

      <p>In cart: {cartIds.length} items</p>
    </div>
  );
}

export default ProductList;

Notes

React.memo is an optimization tool for function components. It controls React's default behavior of re-rendering child components whenever the parent re-renders, and reuses the previous rendering result if props have not changed.

However, for reference-type props such as objects, arrays, and functions, if a new instance is generated each time, they are judged as "different even if the value is the same." Therefore, it is important to stabilize references by combining useCallback for callback functions and useMemo for computed objects.

Passing a comparison function as the second argument allows finer control, such as comparing only specific props. The comparison function returns true to skip re-rendering, and false to allow re-rendering (note that this is the opposite of the return value meaning of shouldComponentUpdate).

Applying React.memo indiscriminately to all components adds the overhead of the comparison itself. It is best to limit its use to components where rendering is costly (high computation or many children).

Related pages: useMemo / useCallback / component / props

Common Mistakes

Passing a callback function as props without useCallback invalidates memo

React.memo checks props with a shallow comparison. If a new function object is generated every time the parent re-renders, the function reference changes, making React.memo ineffective. Memoize the function with useCallback to stabilize the reference.

fighter_ng.jsx
import { memo, useState } from 'react';

const FighterCard = memo(function FighterCard({ name, onSelect }) {
  console.log('render:', name);
  return <button onClick={onSelect}>{name}</button>;
});

function App() {
  const [selected, setSelected] = useState('');

  // A new function is generated every time App re-renders
  // Even with memo, FighterCard re-renders every time because the reference changes
  function handleSelect() { setSelected('Son Goku'); }

  return (
    <div>
      <FighterCard name="Son Goku" onSelect={handleSelect} />
      <p>Selected: {selected}</p>
    </div>
  );
}

After fix:

fighter_ok.jsx
import { memo, useState, useCallback } from 'react';

function App() {
  const [selected, setSelected] = useState('');

  // Memoize the function with useCallback to stabilize the reference
  const handleSelect = useCallback(function() { setSelected('Son Goku'); }, []);

  return (
    <div>
      <FighterCard name="Son Goku" onSelect={handleSelect} />
      <p>Selected: {selected}</p>
    </div>
  );
}

Applying React.memo to all components increases comparison overhead

React.memo adds the cost of the comparison process. Applying it to a component that re-renders frequently with many prop changes can cause the comparison cost to exceed the rendering cost, actually degrading performance. Limit React.memo to components where rendering is costly (high computation or many children).

If you find any errors or copyright issues, please .