What is React.memo() vs useMemo() Hook in React

What is React.memo()?

React.memo() was released with React v16.6. While class components already allowed you to control re-renders with the use of PureComponent or shouldComponentUpdate, React 16.6 introduced the ability to do the same with functional components.

React.memo() is a higher-order component (HOC), which is a fancy name for a component that takes a component as a prop and returns a component that prevents a component from re-rendering if the props (or values within it) have not changed.

We’ll take the same example above but use React.memo() in our component. All we need to do is wrap our component with React.memo() like below:

Screenshot 2021-11-07 171052.jpg

Now, when we select a cheese type by clicking on it, our component will not re-render.

What is useMemo()?

While React.memo() is a HOC, useMemo() is a React Hook. With useMemo(), we can return memoized values and avoid re-rendering if the dependencies to a function have not changed.

To use useMemo() within our code, React developers have some advice for us:

You may rely on useMemo() as a performance optimization, not as a semantic guarantee Every value referenced inside the function should also appear in the dependencies array For our next example, we’ll make some changes to our . The code below only shows the new changes to the we previously created.

// 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++;

  // uncomment the next line to test that <UseMemoCounts /> will re-render every t ime the parent re-renders.
  // const memoizedValue = useMemoRef.current++;

// the next line ensures that <UseMemoCounts /> only renders when the times value changes
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>
  );
}

First, we’re bringing in the all-important useMemo() Hook. We’re also bringing in the useRef() Hook to help us track how many re-renders have occurred in our component. Next, we declare a times state that we will later update in order to trigger/force a re-render.

Afterward, we declare a memoizedValue variable that stores the value returned by the useMemo() Hook. The useMemo() Hook calls our incrementUseMemoRef function, which increments the value of our useMemoRef.current by one each time there is a change in the dependencies, i.e., the times value changes.

We then create a button that updates the value of times when clicked. Clicking this button will cause our useMemo() Hook to be triggered, the value of memoizedValue to update, and our component to re-render.

For this example, we’ve also renamed our component to , and it now takes a memoizedValue prop.

Here’s what it looks like:

// 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} time(s)</span> </p>
    </div>
  );
}
export default UseMemoCounts;

Now, when we click any of the cheese buttons, our memoizedValue does not update. But when we click the Force render button, we see that our memoizedValue updates and the component re-renders.