Frontend Development 12 min read

When to Use React.memo vs useMemo: A Practical Comparison

This article explains memoization, demonstrates why it matters in React, and provides side‑by‑side examples of React.memo and useMemo, showing how each technique can prevent unnecessary re‑renders and improve performance in functional components.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
When to Use React.memo vs useMemo: A Practical Comparison

What is memoization?

Memoization is a technique that caches the results of expensive function calls so that subsequent calls with the same arguments can return the cached value instantly, avoiding redundant computation.

<code>function fibonacci(n){
  return (n < 2) ? n : fibonacci(n-1) + fibonacci(n-2);
}</code>

The naive Fibonacci implementation above repeats many calculations, making memoization a useful optimization.

Why use memoization in React?

In a React function component, any change to props triggers a full re‑render of the component, even if the unchanged parts do not need to update. Memoization can stop unnecessary renders.

Note: the example uses classNames from Tailwind CSS.

Below is a simple parent component that lets a user select a cheese type and shows the best‑matching wine. A child component (

&lt;Counts /&gt;

) tracks how many times the parent re‑renders.

<code>// components/parent-component.js
import Counts from "./counts";
import Button from "./button";
import { useState, useEffect } from "react";
import constants from "../utils";
const { MOZARELLA, CHEDDAR, PARMESAN, CABERNET, CHARDONAY, MERLOT } = constants;
export default function ParentComponent(){
  const [cheeseType, setCheeseType] = useState("");
  const [wine, setWine] = useState("");
  const whichWineGoesBest = () => {
    switch (cheeseType){
      case MOZARELLA: return setWine(CABERNET);
      case CHEDDAR: return setWine(CHARDONAY);
      case PARMESAN: return setWine(MERLOT);
      default: CHARDONAY;
    }
  };
  useEffect(()=>{
    let mounted = true;
    if(mounted){ whichWineGoesBest(); }
    return () => (mounted = false);
  },[cheeseType]);
  return (
    <div className="flex flex-col justify-center items-center">
      <h3 className="text-center dark:text-gray-400 mt-10">Without React.memo() or useMemo()</h3>
      <h1 className="font-semibold text-2xl dark:text-white max-w-md text-center">
        Select a cheese and we will tell you which wine goes best!
      </h1>
      <div className="flex flex-col gap-4 mt-10">
        <Button text={MOZARELLA} onClick={()=> setCheeseType(MOZARELLA)} />
        <Button text={CHEDDAR} onClick={()=> setCheeseType(CHEDDAR)} />
        <Button text={PARMESAN} onClick={()=> setCheeseType(PARMESAN)} />
      </div>
      {cheeseType && (
        <p className="mt-5 dark:text-green-400 font-semibold">
          For {cheeseType}, <span className="dark:text-yellow-500">{wine}</span> goes best.
        </p>
      )}
      <Counts />
    </div>
  );
}
</code>

The

&lt;Counts /&gt;

component simply counts renders:

<code>// components/counts.js
import { useRef } from "react";
export default function Counts(){
  const renderCount = useRef(0);
  return (
    <div className="mt-3">
      <p className="dark:text-white">
        Nothing has changed here but I've now rendered: 
        <span className="dark:text-green-300 text-grey-900">{(renderCount.current++)} time(s)</span>
      </p>
    </div>
  );
}
</code>

When the cheese button is clicked, the parent re‑renders, causing

&lt;Counts /&gt;

to re‑render as well, even though its output does not depend on the selected cheese.

What is React.memo()?

React.memo()

(introduced in React v16.6) is a higher‑order component that wraps a functional component and prevents it from re‑rendering unless its props change.

<code>import { useRef } from "react";
function Counts(){
  const renderCount = useRef(0);
  return (
    <div className="mt-3">
      <p className="dark:text-white">
        Nothing has changed here but I've now rendered: 
        <span className="dark:text-green-300 text-grey-900">{(renderCount.current++)} time(s)</span>
      </p>
    </div>
  );
}
export default React.memo(Counts);
</code>

After wrapping

Counts

with

React.memo

, clicking a cheese button no longer triggers a re‑render of the

&lt;Counts /&gt;

component.

What is useMemo()?

useMemo()

is a React hook that memoizes a computed value and recomputes it only when one of its dependencies changes.

You can rely on useMemo() as a performance optimization, not a semantic guarantee

Every value referenced inside the function should appear in the dependency array

Example parent component using

useMemo

to control when a child re‑renders:

<code>// components/parent-component.js
import { useState, useEffect, useRef, useMemo } from "react";
import UseMemoCounts from "./use-memo-counts";
export default function ParentComponent(){
  const [times, setTimes] = useState(0);
  const useMemoRef = useRef(0);
  const incrementUseMemoRef = () => useMemoRef.current++;
  const memoizedValue = useMemo(() => incrementUseMemoRef(), [times]);
  return (
    <div className="flex flex-col justify-center items-center border-2 rounded-md mt-5 dark:border-yellow-200 max-w-lg m-auto pb-10 bg-gray-900">
      <div className="mt-4 text-center">
        <button className="bg-indigo-200 py-2 px-10 rounded-md" onClick={() => setTimes(times+1)}>
          Force render
        </button>
        <UseMemoCounts memoizedValue={memoizedValue} />
      </div>
    </div>
  );
}
</code>

The

UseMemoCounts

component only re‑renders when

memoizedValue

changes:

<code>// components/use-memo-counts.js
function UseMemoCounts({memoizedValue}){
  return (
    <div className="mt-3">
      <p className="dark:text-white max-w-md">
        I'll only re‑render when you click <span className="font-bold text-indigo-400">Force render.</span>
      </p>
      <p className="dark:text-white">I've now rendered: <span className="text-green-400">{memoizedValue}</span> time(s)</p>
    </div>
  );
}
export default UseMemoCounts;
</code>

Clicking a cheese button does not update

memoizedValue

, so

UseMemoCounts

stays unchanged. Pressing the “Force render” button increments the counter and causes the component to re‑render.

Memoization should be used only when a measurable performance gain is needed, because it consumes additional memory.

Summary: Main differences between React.memo() and useMemo()

React.memo()

is a higher‑order component that prevents a component from re‑rendering unless its props change.

useMemo()

is a hook that memoizes a computed value and recomputes it only when its dependency array changes.

Both tools can improve performance, but they address different problems and should be applied judiciously.

frontendperformanceReactMemoizationuseMemoReact.memo
Tencent IMWeb Frontend Team
Written by

Tencent IMWeb Frontend Team

IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.