Optimize React Render using useMemo, useCallback, and React.memo

Yosua Halim
4 min readSep 6, 2022

--

Photo by Susan Q Yin on Unsplash

Maintaining code that have so many contributor is harder than I thing, don’t you agree? It’s a first time in 2022 that I work with company that have many developer on frontend site and there is a chance that your coworker did some anti-pattern and made the app slower than before.

You can read more about React antipattern here

Today I will share how to Optimize React Application and the most popular way to do this is using useMemo, useCallback, and React.memo.

What is re-render in React?

When talking about React performance, there are two major stages that we need to care about:

  • initial render — happens when a component first appears on the screen
  • re-render — second and any consecutive render of a component that is already on the screen

When React components re-render itself?

There are four reasons why a component would re-render itself:

  • state changes
  • parent (or children) re-renders
  • context changes,
  • hooks changes

useMemo vs useCallback

Fundamentally, useMemo and useCallback are tools built to help us optimize re-renders. They do this in two ways:

  1. Reducing the amount of work that needs to be done in a given render.
  2. Reducing the number of times that a component needs to re-render.

Simple explanation:

  • useMemo returns a memoized value.
const memo = useMemo(() => fn, deps)
  • useCallback returns a memoized callback
const callback = useCallback(fn, deps)

useMemo

Our application has two pieces of state, selectedNum and time. Once per second, the time variable is updated to reflect the current time, and that value is used to render a digital clock in the top-right corner.

Here’s the issue: whenever either of these state variables change, we re-run all of those expensive prime-number computations. And because time changes once per second, it means we're constantly re-generating that list of primes, even when the user's selected number hasn't changed!

Solution : You can wrap the allPrimes function with React.useMemo, This will prevent the allPrimes being called every seconds.

useMemo takes two arguments:

  1. A chunk of work to be performed, wrapped up in a function
  2. A list of dependencies

In this case, we’re essentially saying “recalculate the list of primes only when selectedNum changes”. When the component re-renders for other reasons (eg. the time state variable changing), useMemo ignores the function and passes along the cached value.

This is commonly known as memoization, and it’s why this hook is called “useMemo”.

useCallback

useCallback serves the same purpose as useMemo, but it's built specifically for functions. We hand it a function directly, and it memoizes that function, threading it between renders.

UseMemo

Instead of returning an array, we’re returning a function. This function is then stored in the calculate variable.

This works… but there’s a better way:

useCallback

React.memo

Alternatively you can use React.memo to prevent the re-renders

Wrapping a component in React.memo will stop the downstream chain of re-renders that is triggered somewhere up the render tree, unless this component’s props have changed.

This is known as a pure component. Essentially, we’re telling React that this component will always produce the same output given the same input, and we can skip the re-renders where nothing’s changed.

This can be useful when rendering a heavy component that is not dependent on the source of re-renders (i.e. state, changed data).

This is so important because if you have many components within 1 file and you want only render 1 component, React.memo is the answer.

Bonus Tips

Creating components inside render function of another component is an anti-pattern that can be the biggest performance killer. On every re-render React will re-mount this component (i.e. destroy it and re-create it from scratch), which is going to be much slower than a normal re-render.

If you liked this article, you might want to clap for it because it would help me out a lot. Thank you!

--

--

Yosua Halim

Software Engineer, love all about technologies and love to learn.