You can use memoization in plain JavaScript and also in React, in a few different ways.

Memoization in JavaScript

To memoize a function in JavaScript, you need to store the results of that function in a cache. The cache can be an object with the arguments as keys and results as values.

When you call this function, it first checks whether the result is present in the cache before running. If it is, it returns the cached results. Otherwise, it executes.

Consider this function:

The function takes in an argument and returns its square.

To run the function, call it with a number like this:

With 5 as the argument, square() will run pretty fast. However, if you were to calculate the square of 70,000, there would be a noticeable delay. Not by much but a delay nonetheless. Now, if you were to call the function multiple times and pass 70,000, you would experience a delay in each call.

You can eliminate this delay using memoization.

In this example, the function checks whether it’s computed the result before, by checking if it exists in the cache object. If it has it returns the already computed value.

When the function receives a new number, it calculates a new value and stores the results in the cache before it returns.

Again this example is pretty simple, but it explains how memoization would work to improve the performance of a program.

You should only memoize pure functions. These functions return the same result when you pass the same arguments in. If you use memoization on impure functions, you will not improve performance but increase your overhead. That’s because you choose speed over memory every time you memoize a function.

Memoization in React

If you are looking to optimize React components, React provides memoization through the useMemo() hook, React.memo, and useCallBack().

Using useMemo()

useMemo() is a React hook that accepts a function and a dependency array.

It memoizes the value returned from that function. The values in the dependency array dictate when the function is executed. Only when they change is the function executed again.

For example, the following App component has a memoized value called result.

The App component calls square() on every render. The performance will degrade if the App component is rendered many times due to React props changing or state updating, especially if the square() function is expensive.

However, since useMemo() caches the returned values, the square function is not executed in each re-render unless the arguments in the dependency array change.

Using React.memo()

React.memo() is a higher order component that accepts a React component and a function as arguments. The function determines when the component should be updated.

The function is optional and if not provided, React.memo makes a shallow copy comparison of the component’s current props to its previous props. If the props are different, it triggers an update. If the props are the same, it skips the re-render and reuses the memoized values.

The optional function accepts the previous props and the next props as arguments. You can then explicitly compare these props to decide whether to update the component or not.

Let’s look at an example without the optional function argument first. Below is a component called Comments that accepts the name and email props.

The memoized comments component will have React.memo wrapped around it like this:

You can call then call it like any other React component.

If you want to perform the props comparison yourself, pass the following function to React.memo as the second argument.

If checkProfileProps returns true, the component is not updated. Otherwise, it is re-rendered.

The custom function is useful when you want to customize the re-render. For example, you could use it to update the Comments component only when the number of likes changes.

Unlike the useMemo() hook that memoizes only the returned value of a function, React.memo memoizes the whole function.

Use React.memo only for pure components. Also, to reduce comparison costs, only memoize components whose props change often.

Using useCallBack()

You can use the useCallBack() hook to memoize function components.

The function gets updated only when the values in the dependency array change. The hook works like the useMemo() callback, but it memoizes the function component between renders instead of memoizing values.

Consider the following example of a memoized function that calls an API.

The getData() function called in useEffect will be called again only when the getData value changes.

Should You Memoize?

In this tutorial, you learned what memoization is, its benefits, and how to implement it in JavaScript and React. However, you should know that React is already fast. In most cases, memoizing components or values adds comparison costs and doesn’t improve performance. Because of this, only memoize expensive components.

React 18 also introduced new hooks like useId, useTransition, and useInsertionEffect. You can use these to improve the performance and user experience of React applications.