Barry Michael Doyle Profile Picture
Barry Michael Doyle
Posted on Nov 6, 2023 • Updated on Nov 12, 2023

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

#JavaScript#Performance#Programming#ReactJS

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>; };

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)

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

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>; };

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>; };

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!