To `useMemo` or Not to `useMemo`: A React Developer’s Dilemma

Barry Michael Doyle - Sep 20 '23 - - Dev Community

Hey React devs! Today, we’re diving into the useMemo hook - a tool that can speed up our apps but can also complicate things if not used wisely.

So, what’s the deal with useMemo? Well, it's a hook that helps us optimize function executions by “remembering” the previous results, and only redoing the work if the inputs change. It’s like having a super-smart assistant that remembers everything, ensuring our app runs faster and smoother. Handy, right?

But here’s a little story. A while back, someone on my team got really into useMemo and started using it everywhere. I mean, everywhere! And while it’s fabulous, it’s not supposed to be a one-size-fits-all solution; otherwise, we’d have a useWithoutMemo hook built into React!

A meme showing that beginners never useMemo, intermediates always useMemo and experts never useMemo.

To save you from the useMemo everywhere trap, I've compiled this guide where we explore the best spots and not-so-great spots to use useMemo. Let's jump in!

When to Use useMemo

useMemo shines in these scenarios:

1. Complex Calculations

When your component deals with heavy computations, useMemo ensures these only re-run when necessary, keeping the performance sleek.

function complexCalculation(list) {
  // Complex calculation here
  return result;
}

function MyComponent({ list }) {
  const memoizedResult = useMemo(() => {
    return complexCalculation(list)
  }, [list]);

  return <div>{memoizedResult}</div>;
};
Enter fullscreen mode Exit fullscreen mode

2. Maintaining Referential Equality

useMemo helps in keeping the same reference for objects or arrays when passing them as props, avoiding needless renders.

function MyComponent({ values }) {
  const memoizedValues = useMemo(() => values, [values]);

  return <MemoizedChildComponent values={memoizedValues} />;
};

function ChildComponent({ values }) {
  // ...
});

const MemoizedChildComponent = React.memo(ChildComponent)
Enter fullscreen mode Exit fullscreen mode

3. Filtering or Sorting Large Lists

When working with large datasets, using useMemo for filtering or sorting prevents these operations from rerunning during every render, saving precious computing power.

function MyComponent({ list }) {
  const filteredList = useMemo(() => {
    return list.filter(item => item.active);
  }, [list]);

  return <ListDisplay items={filteredList} />;
};
Enter fullscreen mode Exit fullscreen mode

When Not to Use useMemo

useMemo is not always the hero we deserve. Here’s when it can be counterproductive:

1. Simple Calculations

For basic calculations, bringing in useMemo can complicate things more than helping.

function MyComponent({ value }) {
  // Not recommended for simple calculations
  const multipliedValue = useMemo(() => {
    return value * 2;
  }, [value]);

  return <div>{multipliedValue}</div>;
};
Enter fullscreen mode Exit fullscreen mode

2. Working with Primitive Values

Memoizing primitive values, like numbers or strings, is generally overkill as they don't cause unnecessary renders.

function MyComponent({ value }) {
  // Not recommended for primitive values
  const memoizedValue = useMemo(() => value + 1, [value]);

  return <div>{memoizedValue}</div>;
};

### 3. Frequent Changes in Dependencies

If the inputs change a lot, `useMemo` loses its efficiency because it ends up recalculating often.

function MyComponent({ frequentlyChangingValue }) {
  // Not recommended for frequently changing dependencies
  const memoizedValue = useMemo(() => {
    return expensiveCalculation(frequentlyChangingValue);
  }, [frequentlyChangingValue]);

  return <div>{memoizedValue}</div>;
};
Enter fullscreen mode Exit fullscreen mode

Conclusion

Remember, it’s not about using useMemo everywhere, but about using it wisely. Start with the simple approach first, and then optimize as needed, avoiding premature optimization.

I hope this guide sets you on the path to creating more efficient React apps. Happy coding!

. . . . . . . . . . .