React memo Practice Questions with Solutions

Introduction

React.memo is a React performance optimization that allows a component to skip re-rendering when its props have not changed. It is especially useful for components that render frequently and receive the same props. However, React.memo does not prevent every re-render and should be used when it provides a meaningful performance benefit. In this chapter, we will solve practical questions about memoized components, props comparison, and useCallback. React memo Practice Questions with Solutions help to understand the concepts.

1. What is React.memo?

React.memo is a React API that lets you memoize a component.

Example:

import { memo } from "react";

const User = memo(function User({ name }) {
  return <h2>{name}</h2>;
});

export default User;

When the parent component renders again, React can skip rendering the memoized User component if its props have not changed.

React.memo is mainly used as a performance optimization.


2. Why is React.memo used in React?

Normally, when a parent component renders, its child components may also render.

For example:

function Child({ name }) {
  console.log("Child rendered");

  return <h2>{name}</h2>;
}

You can memoize the child:

import { memo } from "react";

const Child = memo(function Child({ name }) {
  console.log("Child rendered");

  return <h2>{name}</h2>;
});

If the parent renders again but name remains the same, React can skip rendering the memoized child.

This can be useful when the child is expensive to render or renders frequently.


3. How do you create a memoized component using React.memo?

Pass a component to memo().

import { memo } from "react";

function Product({ name, price }) {
  return (
    <div>
      <h2>{name}</h2>
      <p>Price: ₹{price}</p>
    </div>
  );
}

const MemoizedProduct = memo(Product);

export default MemoizedProduct;

You can also write it directly:

const Product = memo(function Product({ name, price }) {
  return (
    <div>
      <h2>{name}</h2>
      <p>Price: ₹{price}</p>
    </div>
  );
});

Both approaches create a memoized component.


4. How does React.memo decide whether to re-render a component?

By default, React.memo compares the component’s previous and new props using a shallow comparison based on Object.is.

For primitive values such as strings and numbers:

<Product name="Laptop" price={50000} />

If the values remain the same, the memoized component can skip a render caused by the parent.

However, objects, arrays, and functions are compared by reference.

For example:

const user = {
  name: "Ravi"
};

A newly created object can have a different reference even when it contains the same values.

Therefore, React.memo does not perform a deep comparison of objects.


5. Can React.memo prevent all re-renders?

No.

React.memo only controls re-rendering caused by unchanged props from the parent.

A memoized component can still re-render when:

  • Its own state changes.
  • A context value it uses changes.
  • Its props change.
  • Its parent passes a different prop reference.

Example:

const Counter = memo(function Counter() {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(count + 1)}>
      {count}
    </button>
  );
});

Changing the component’s own state still causes it to render.

So, React.memo is not a guarantee that a component will never render again.


6. How does React.memo work with useCallback?

This is a common combination for performance optimization.

Suppose a parent passes a function to a memoized child:

const handleClick = () => {
  console.log("Clicked");
};

A new function reference can be created when the parent renders.

useCallback can keep the function reference stable:

const handleClick = useCallback(() => {
  console.log("Clicked");
}, []);

Then:

const Button = memo(function Button({ onClick }) {
  return <button onClick={onClick}>Click</button>;
});

This combination can allow the memoized child to skip re-rendering when its other props remain unchanged.

React.memo and useCallback solve related but different problems:

  • React.memo memoizes a component.
  • useCallback memoizes a function reference.

7. What happens when an object is passed to a memoized component?

Objects are compared by reference, not by their contents.

Example:

const User = memo(function User({ user }) {
  console.log("User rendered");

  return <h2>{user.name}</h2>;
});

function App() {
  const user = {
    name: "Ravi"
  };

  return <User user={user} />;
}

If a new user object is created on each parent render, the object reference can change.

Therefore, the memoized component may render again even though user.name is still "Ravi".

The important point is that React.memo does not automatically perform deep object comparison.


8. Can you provide a custom comparison function to React.memo?

Yes.

memo can receive an optional comparison function.

Example:

const User = memo(
  function User({ name, age }) {
    return (
      <div>
        <h2>{name}</h2>
        <p>{age}</p>
      </div>
    );
  },
  (previousProps, nextProps) => {
    return (
      previousProps.name === nextProps.name &&
      previousProps.age === nextProps.age
    );
  }
);

The comparison function returns:

  • true → props are considered equal, so React can skip the render.
  • false → props are considered different, so React renders the component.

Custom comparisons should be used carefully because an expensive comparison can itself reduce or eliminate the performance benefit.


9. When should you use React.memo?

React.memo can be useful when:

  • A component renders frequently.
  • The component receives the same props often.
  • Rendering the component is relatively expensive.
  • Parent components update frequently.
  • Profiling shows that memoization can improve performance.

For a small and inexpensive component, adding React.memo may provide little or no practical benefit.

It is better to use memoization based on an actual performance need rather than automatically wrapping every component.


10. Build a Practical Product List using React.memo

Create a product list where each product is a memoized component.

Solution:

import { memo, useCallback, useState } from "react";

const Product = memo(function Product({ product, onSelect }) {
  console.log("Product rendered:", product.name);

  return (
    <div>
      <h3>{product.name}</h3>
      <p>Price: ₹{product.price}</p>

      <button onClick={() => onSelect(product.id)}>
        Select
      </button>
    </div>
  );
});

function ProductList() {
  const [selectedProduct, setSelectedProduct] = useState(null);
  const [theme, setTheme] = useState("Light");

  const products = [
    { id: 1, name: "Laptop", price: 50000 },
    { id: 2, name: "Mouse", price: 1000 },
    { id: 3, name: "Keyboard", price: 2000 },
  ];

  const handleSelect = useCallback((id) => {
    setSelectedProduct(id);
  }, []);

  return (
    <div>
      <h1>Products</h1>

      <p>Theme: {theme}</p>

      <button
        onClick={() =>
          setTheme((previousTheme) =>
            previousTheme === "Light" ? "Dark" : "Light"
          )
        }
      >
        Change Theme
      </button>

      {products.map((product) => (
        <Product
          key={product.id}
          product={product}
          onSelect={handleSelect}
        />
      ))}

      <p>
        Selected Product:{" "}
        {selectedProduct ?? "None"}
      </p>
    </div>
  );
}

export default ProductList;

How it works:

  • Product is wrapped with memo.
  • Each product receives a product object and onSelect callback.
  • handleSelect is memoized with useCallback.
  • The key provides stable identity for each list item.
  • When the theme changes, the callback reference remains stable.
  • Memoization can help avoid unnecessary child renders when the relevant props remain unchanged.

Important: In this example, the products array is recreated during every ProductList render. Therefore, each product object can also receive a new reference. In a real optimization scenario, you may need to stabilize or otherwise structure the data before expecting React.memo to skip those renders.

Key Takeaways

  • React.memo is used to memoize a component.
  • It can allow a component to skip re-rendering when its props have not changed.
  • By default, props are compared using shallow comparison based on Object.is.
  • Objects, arrays, and functions are compared by reference.
  • React.memo does not perform deep comparison automatically.
  • A memoized component can still re-render because of its own state or context changes.
  • useCallback can help keep function props stable.
  • React.memo and useCallback are often used together when function props are involved.
  • A custom comparison function can be provided to memo().
  • React.memo is a performance optimization, not a requirement for every component.
  • Profiling and actual performance needs should guide memoization decisions.

FAQs

1. What is React.memo?

React.memo is a React API that memoizes a component and can allow React to skip rendering it when its props have not changed.

2. Why should I use React.memo?

Use it when a component renders frequently with the same props and avoiding its repeated rendering can provide a meaningful performance benefit.

3. Does React.memo prevent re-renders?

No. It can skip re-renders caused by unchanged parent props, but state changes, context changes, or changed props can still cause a memoized component to render.

4. How does React.memo compare props?

By default, React compares each prop using Object.is. Objects, arrays, and functions are therefore compared by reference.

5. What is the difference between React.memo and useCallback?

React.memo memoizes a component, while useCallback memoizes a function reference.

6. Can I pass a custom comparison function to React.memo?

Yes. memo() accepts an optional comparison function that can determine whether the previous and next props should be treated as equal.

7. Should every React component use React.memo?

No. React.memo should be used when it provides a meaningful performance benefit. Unnecessary memoization can add complexity without improving performance.

Written by Shubhranshu Shekhar, who has trained 20000+ students in coding.

Scroll to Top