Memoization in React with Functional Components: Part 1

Aidan McBride
3 min readOct 9, 2022

React is a lightweight frontend library with many features to optimize performance. One of such features available in React is memoization. Memoization is defined as

“…an optimization technique that makes applications more efficient and hence faster. It does this by storing computation results in a cache, and retrieving that same information from the cache the next time it’s needed instead of computing it again.” ²

Thinking in terms of component based react development, think of “computation results” as functional components. Memoization is possible with class components as well, but this article will only cover functional components.

Use Case

A common use of memoization in React is preventing a child component from re-rendering when it does not need to. For example, if a parent component updates some state value that does not involve the child, by default React will re-render the child component. Using memoization however, we can restrict the re-rendering of child components to reduce unnecessary load.

The Problem

Below we have Table functional component with two separate states, count and buttonData. The button that changes the count state exists in the parent component, and that state is not passed to any of its children. For this reason, we do not want Button to re-render when count is changed, because they do not have anything to do together.

Lines 20–22 render a list of custom Button components

Here is the custom Buttoncomponent that the Table component renders.

A console log is present to easily show when the component is rendered

Important: note that the props being passed to Button are destructured. When memo compares previous and new props, it only uses a shallow comparison, so a props object will always cause a re-render. This is because additional overhead is required to compare a complex data structure.³
As this code stands, every time the count state is updated in the Table parent component, the Button child component will re-render. This is a waste of computation and can be prevented to increase performance.

The Solution

In order to prevent these costly and unnecessary re-renders, all we have to do is use memo on the Button component.

memo is imported from ‘react’

As noted above, this memoizes the Button component, so that every time it is attempted to re-render, it will first compare the last set of props passed to the current set of props passed. Since both id and label have not changed at all, the component does not need to re-render.

Now, whenever you change the count state in the parent Table component (or any other state unrelated to buttonData for that matter), the child Button component will compare it’s previous and current props, and decide not to re-render.

When You DO Want to Re-render

Assuming you only want to re-render the child component when its own state changes, all you have to do is update the state correctly. The example bellow will not re-render the child component.

There is a console log on line 6 to show when this table component renders

Note line 22. What we are doing here is creating a copy of state, changing one property on one of the objects within the state array, and setting state with that same array. The useState hook see’s this as updating state with its old state, and therefore will not trigger a render. The very simple solution to this is below.

Spread operator on line 6

The solution here is to use the spread operator, “spreading” the array into a new array. This will trigger the parent component to render, passing new props (id and label) to the child Button component. memo will compare the old props with the new, and since now the props have actually changed, the component will render again.

One other thing to note here, is that only the Button component with the changed props values will be rendered, not the entire list of Buttons.

Keep In Mind

Memoizing a functional component only compares the props that are sent to the component to determine rendering. If the Button component itself has state or context, utilizing the useState, useReducer, or useContext hooks then it will render as expected.

In Part 2 I will discuss useCallback, useMemo, and useRef.

GitHub:

https://github.com/AidanMcB/Memoization-in-React/tree/memoization-part-1

Resources:

  1. https://reactjs.org/docs/react-api.html#reactmemo
  2. https://www.freecodecamp.org/news/memoization-in-javascript-and-react/#:~:text=In%20programming%2C%20memoization%20is%20an,instead%20of%20computing%20it%20again.
  3. https://blog.openreplay.com/improving-react-application-performance-react-memo-vs-usememo/#:~:text=memo%20utilizes%20shallow%20comparison%20by,the%20worse%20the%20overhead%20is.

--

--

Aidan McBride

I am a Front End Engineer and graduate of Flat Iron coding bootcamp. Currently I work in the regulatory industry using React.