Read article Return to blog

Memoization in React - What the heck is memoization and how to memoize your React components to improve performance

Posted August 12, 2021

5-7 min read

Yes, you read that word right. Memoization. It sounds like it shouldn't even be a real word. But in the realm of software development where engineers often obsess over optimizing the performance of their programs, it's certainly okay to make up a new word to coin an incredible development technique that can significantly increase the performance of your applications (and most importantly, can be easily implemented in React!).

In basic terms, memoization is a programming technique in which an application caches specific parameter values provided to a unique memory intensive function call when it is invoked, and any successive calls of this individual memoized function will compare the newly provided parameter values to our cached parameter values from the function's previous invocation. If the new parameter values provided to a memoized fuction's successive invocation are the same as our cached parameter values from its previous call, we know that it will return the same value we already have in memory, thus we can tell our function to skip this successive invocation altogether. For any programming language, when we write a function where a specific output is desired based on unique parameter values provided in the function call, why should we need to rerun the function if we already have the return value available? Memoization solves this problem.

In React we are able to memoize not only variables that get their assigned values from function calls that require unique parameter values, but we can also memoize entire functional components (keyword functional components - if we want to memoize/optimize a class component we could extend React's PureComponent class, but let's leave that for another blog post). There are two key memoization implementations the React framework provides to developers that we'll need to distinguish the difference between. First there is React.memo(), a higher-order component that we can wrap around our custom written functional components with the goal of preventing unncessary rerenders if the component's provided prop values have not changed since its last render. This specific high order component addresses memoizing an entire functional component. Secondly, if your goal is to memoize a single variable existing within a component that gets its assigned value from a logical function that requires unique parameters, React provides us with a useMemo() hook that can be utilized to achieve this same optimization goal. For this article, we are going to focus on learning the benefits of memoizing entire custom functional components. Lets look at an example of leveraging React.memo() to reduce the amount of the total # of rerenders for an example app that i've written for this post. Before we demonstrate implementing a memoized component, lets take a peak at an example React app that has no memoization logic implemented in the code to see the unnecessary amount of rerenders that can occur. This demo application contains a parent <App> component that holds a secondsSinceMount state value tracking the elapsed time (in seconds) since its initial render. Within our <App> component we have a child <Quiz> component which expects two props: a title string which represents the main header title, as well as a questions array which expects objects that include two keys: label, a given question's left-side main label as well as choices, an array of strings which populate a corresponding question's radio button selections. Since we have a state updating every second in the parent <App> component and the child <Quiz> component is unmemoized, you'll notice in the console logs that both components are forced to rerender each time the secondsSinceMount integer state variable existing in <App> is updated.

Open that console up and notice how both the <App> and <Quiz> components are rerendering for each state update occuring in <App>. Not ideal!

Having to rerender the <App> component is necessary because it contains a constantly changing state variable that we are displaying to the end user. But looking at the console logs, you can see that our child <Quiz> component rerenders itself each time this parent state value updates. If the provided props to our <Quiz> component are constant (provided to us in dummyData.js for this example), it is certainly a waste of our precious memory to constantly rerender this child component when its provided props are not ever being updated. In this next example we'll take a look at a demo implementation of React.memo() for our <Quiz> component so that we can avoid these unnecessary rerenders observed in this first example.

Open up the console again and notice how our new and <MemoizedQuiz> component only requires one initial render. Much better! :D

Diving into our Quiz.js file, take a look at how we are no longer exporting <Quiz> as our component to use in App.js, but instead wrapping this functional component in a React.memo() call at the bottom of the file and exporting a new memoized component variable that we'll call <MemoizedQuiz>. Taking a peak at the console logs, we can now see that the <MemoizedQuiz> component does not need to rerender itself each time the secondsSinceMount parent state variable is updated because its provided prop values are constant/unchanging and it is wrapped inside of a React.memo() high order component. We are able to cut the amount of total rerenders in half! While this is a very rudimentary example, if we think about large-scale React apps that have hundreds of parent/child component relationships, memoization is a beautiful optimization technique that can potentially have a significant impact on a React application's performance. The less rerenders that occur within a React application, the better its overall performance will be. Memoization is a programming technique that shouldn't be disregarded or looked at as an insignificant optimization approach when writing a React application, especially if any given React child components are not digesting changing state data from one of its parent components.

If you have any insights, comments, or questions about debouncing feel free to reach out to me via the contact section below. Thanks for reading!

( P.S. British artificial intelligence pioneer Donald Michie was the first computer scientist to implement memoization, coining the term in 1968. )

Contact me

Tucker Massad

Boston, MA

tuckermassad@gmail.com