engineering

Memo-tional Choices: Embracing or Evading useMemo

useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).

  • react
  • javascript
  • performance
  • web-development
  • front-end-development

Summary

What
useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).
Who it is for
Developers and engineers interested in practical frontend and tooling notes.
Result
A clear takeaway you can apply in day-to-day engineering work.

TL;DR

useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).

If you know the significance of passing a function reference versus passing an arrow function that calls the function.

Every render vs useMemo

Red = recompute. Blue = cache hit.

Rule: memo when the calc is expensive and deps stay put. Early useMemo is noise.

What useMemo does

It calls a function when dependencies change, memoizes the result between renders.

This is in contrast with useCallback which remembers an existing value (typically a function’s definition), between renders.

You want to use useMemo to save yourself from rerunning an expensive calculation to generate a new value, and you want to use useCallback to store an existing value.

When to use useMemo

You don’t need until you notice parts of your app are frustratingly slow. Early optimisation is not a great idea. And throwing useMemo is early optimisation.

When to consider using useMemo:

Two things to keep in mind,

  • You notice a component’s render is sloooowwww…, and you’re passing a calculation to a ton of children, like when using Array.map(). I’ve had a run with this when I was working with the Onboarding team for the Progressive Onboarding feature.
  • Your app often becomes unresponsive because you’re fetching a large amount of data, and transforming it to a useable format.

The key is to zero in on the problem.

“My app is slow, and calculations are heavy” is something that useMemo can solve.

If you’ve just learnt about useMemo and you’re going “Salt Bae” on it, you’re gonna end up with a sloth (like Flash from Zootopia).

The cost of using it

It’s not free. It comes at a cost: memory usage.

Basically, when we use useMemo, we’re using more memory to free up CPU time. If you take up too much memory, this can quickly outweigh the performance benefit of remembering.

Memory impact with overuse of useMemo

Assumptions:

  • useMemo caches the result of a computation.
  • Overusing useMemo means creating a large number of memoized values that remain in memory.

Memory Impact Without Overuse:

  • Let’s assume a project has 100 components, each creating a memoized value of size M bytes.
  • Typical use of useMemo (e.g., in 20% of the components): 0.2 * 100 = 20M bytes.

Memory Impact With Overuse:

  • Overusing useMemo (e.g., in 80% of the components): 0.8 * 100 = 80M bytes.
  • This means 80% of components are holding memoized values, which can lead to significant memory overhead.

Memory Overhead Calculation:

  • Memory overhead due to overuse: 80V − 20M = 60M
  • Percentage increase in memory usage: (60M / 20M) * 100 = 300%

Potential Issues:

  • The increase in memory usage can lead to memory leaks and performance degradation.
  • Garbage collection may not be able to free up memory efficiently if many memoized values are retained unnecessarily.

useMemo can be killer good when used right. If you don’t overdo it and stick to not using it in 80% of your components, you’ll dodge the memoization overhead and reduce the overall memory usage by more than 20%. Just a little moderation goes a long way!Cheers!


Memo-tional Choices: Embracing or Evading useMemo was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


Originally published on Medium.