What is Memoization in React?
Tags: react, webdev, productivity
Published: 2022-06-28 14:17:04

---
title: What is Memoization in React?
published: true
date: 2022-06-28 10:13:09 UTC
tags: react, webdev, productivity
canonical_url: https://www.syncfusion.com/blogs/post/what-is-memoization-in-react.aspx
cover_image: https://www.syncfusion.com/blogs/wp-content/uploads/2022/06/What-is-Memoization-in-React-672x372.png
---

Performance optimization is critical for web applications to maintain a solid user experience. In React, there are instances in which re-rendering a complex component leads to performance issues, impacting the user experience. React offers **memoization** as a performance feature that speeds up component rendering to overcome this hassle.

This article will discuss what memoization is in React and how you can implement it in your React apps.

## What is memoization?

[Memoization](https://en.wikipedia.org/wiki/Memoization "Wikipedia page for Memoization") is an optimization technique for accelerating computer programs by caching the results of heavy function calls and returning them when similar inputs are encountered repeatedly. Simply, React memoization is similar to caching.

As an example, consider a long-running, sophisticated function that accepts input. To speed up this function execution, you can cache the results after executing it. So that, you can take the cached value without recomputing the value whenever you execute it again with the same inputs. Consequently, we can avoid unwanted rerenders for the same resultant output with the same set of inputs. We can capture the initial render result and cache it in memory for later use. This will boost app performance.

## Why use memoization in React?

When props within a React functional component change, the whole component rerenders by default. To put it in another way, if a value inside the component changes, the entire component will rerender, along with all the functions or components whose values or props haven’t changed.

This will result in a performance pitfall, which can be avoided with memoization.

## How to Implement memoization in React

Both functional and class components benefit from memoization. React offers HOCs and hooks to implement this feature. We can use **React.PureComponent** within class components. Memoization for functional components is also possible with **React.memo()** HOC and **useMemo()** Hook. The **useCallback()** Hook is also there for caching functions instead of values.

Now, let’s have a look at these approaches one by one.

## Memoization using PureComponent

**React.PureComponent**  helps us to implement memoization in a class component. **PureComponent** implements **React.ShouldComponentUpdate()**, which performs a shallow comparison of **state** and **props** and only renders the React component if the **props** or **state** have changed.

In this case, we have to keep the props and state as simple as possible. Since  **PureComponent** may yield incorrect results if they include any advanced data structures. As **PureComponent’s shouldComponentUpdate()** avoids **prop** updates for the entire component subtree, we should also ensure that all **PureComponent’s** children are also **PureComponent**.

Refer to the following simple example to implement memoization with **React.PureComponent**.

```js
//Parent.js
import React, {Component} from 'react';
import Child from './Child';
class Parent extends React.Component {
  constructor(props) {
     super(props);
     this.state = { count: 0 };
}

onClick = () => {
  this.setState((prevState) => {
     return { count: prevState.count + 1 };
  });
};

render() {
  console.log("Parent render");
     return (
       <div className="App"><button onClick={this.onClick}>Update Counter</button> <h2>{this.state.count}</h2>
       <Child name={"child"} /></div>
     );
  }
}

export default Parent;
```

The **Child** component should be like this.

```js
//Child.js
import React, {Component, PureComponent} from 'react';
class Child extends React.PureComponent { 
  render() {
    console.log("Child render");
    return (
       <div>
         <h2>{this.props.name}</h2>
       </div>
    );
  }
}

export default Child;
```

When you click on the **Update Counter** in the **Parent** component, it will call both the **Parent** and **Child** components’ render methods for the initial render.

Only the **Parent** component’s render function is invoked for successive rerendering on each update. Therefore, we don’t need the **Child** component for re-rendering.

## How to implement memoization in Functional Components

Let’s see how to use **React.memo()** and **useMemo()** for memoization under this section.

### React.memo()

**React.memo()** is very simple to use because it is identical to **React.PureComponent**. While **React.memo() **works with functional components, **PureComponent** works with class components.

Consider these two components. The **Parent** component will look like this.

```js
const Parent= () => {
  const [counter1, setCounter1] = React.useState(0)
  const [counter2, setCounter2] = React.useState(0)

  const incrementCounter1 = () => {
     setCounter1(counter1=> counter1+ 1)
  }

  return (
    <><button onClick={incrementCounter1}>Increment counter 1</button><Child value={counter1}>Counter 1</Child><Child value={counter2}>Counter 2</Child></>
  )
}
```

And the **Child** component is as follows.

```js
const Child= ({value, child}) => {
  console.log('Render: ', child)

  return (
    <div>
      {child}: {value}
    </div>
  )
}

export default Child;
```

The state of **counter1 Child component** updates whenever the user clicks the **Increment counter 1** button, leading the **Parent** to rerender both **counter Child components** , which can be considered an undesired rerender.

You need to wrap the **Child** component with **React.memo()** to avoid this. It will only force the **Child** component to rerender if the **props** are changed.

```js
const Child= ({value, child}) => {
  console.log('Render: ', child)

  return (
    <div>
      {child}: {value}
    </div>
  )
}

export default React.memo(Child)
```

**Note:** If the component has a **useState** , **useReducer** , or **useContext** Hook, the state or context will still trigger a rerender.

To regulate **memo’s** typical behavior, which shallowly compares complex objects in the **props** object, we have to create a custom comparison function and pass it as the second argument, as follows.

```js
function App(props) {
  /* render using props */
}

function areEqual(prevProps, nextProps) {
  /*
  if results are same when passing prevProps and when 
  passing nextProps then areEqual will return true, if 
  results are not same then it will return false 
  */
}
export default React.memo(App, areEqual);
```

### useMemo()

In React, the **useMemo()** hook is the most fundamental method of memoization. You can use **useMemo()** to implement memoization if you’re a Hooks lover.

To use **useMemo()**, pass a function that performs the heavy computation you want to memoize as the first parameter and an array of all dependencies for that memoization as the second argument. **useMemo()** boosts performance by recalculating the memoized value only if one of the given dependencies changes.

This optimization helps to avoid expensive calculations on every render.

```js
const memoizedValue = useMemo(() =>
   expensiveComputation(a, b), [a, b]
)
```

Let’s consider a simple example for calculating a factorial. When the component renders initially, the **useMemo** Hook calls **FactorialCalc** and memoizes the value calculated before returning the result to the component. The significant point here is that if the list of dependencies **([number])** we provide does not update between renders, **useMemo** will return the **memoizedFactorial** instead of calling **FactorialCalc**.

```js
import { useState, useMemo } from "react";
const App = () => {
  const [number, SetNumber] = useState(1);
  const memoizedFactorial = useMemo(() => FactorialCalc(number), [number]);
   
  const onChange = (e) => {
     console.log(e.target.value);
     SetNumber(Number(e.target.value));
};
return (
  <div><input type="text" onChange={onChange} />
     {memoizedFactorial}
  </div>
);
};
function FactorialCalc(n) {
  console.log('factorialOf(n) called!');
  return n <= 0 ? 1 : n * FactorialCalc(n - 1);
}
export default App;
```

**Note:** Additionally, keep in mind that **useMemo()** executes during rendering. Thus, we should avoid using whatever isn’t used while rendering, such as side effects.

### useCallback()

**useCallback()** is almost equivalent to **useMemo()** in that it memoizes a result relying on an array of dependencies. However, **useCallback() **is only used for memoizing functions rather than values.

When we used the **React.memo()** in the child component in the previous case, the **Child** component did not rerender, although the **Parent** component did. Nevertheless, passing a function as a prop to a **Child** component would still cause the **Child** component to rerender, even with **React.memo()**.

Consider the following example.

```js
//Parent.js
export default function Parent() {
  const [counter, setCounter] = useState(0);
  const handleClick = () => {
      setCounter(counter + 1);
};

const onClick= () => {
  console.log("onClick");    
  // This is the new handler that will be passed to the child
};

console.log("Parent render");
  return (
    <div className="App"><button onClick={handleClick}>Increase</button><h2>{counter}</h2><Child name={"child"} childHandler={onClick} /></div>
  );
}
```

And the **Child** component will look like this.

```js
//Child.js
export function Child(props) {
  console.log("Child render");
  return (
     <div><h2>{props.name}</h2></div>
  );
}

export default React.memo(Child);
```

Even when the **props** provided haven’t changed, when we increase the **counter** in the **Parent** component, it rerenders the **Child** component, as well.

So, what triggers the **Child** component to rerender is that a new **onClick** function is generated and sent to the **Child** component each time the **Parent** component rerenders. Because the **onClick** function is created with each rerender, the **Child** detects that the **onClick** reference has updated and rerenders the **Child** component solely on a basic comparison of **props**.

The **useCallback**  helps us to prevent recreating the method each time the parent component is rendered. We have to introduce the **useCallback()** Hook to the **onClick** function in this case. We can use an empty, a single, or a list of dependencies as the second argument. A memoized result of the callback provided as the first argument is returned if the dependencies specified in **useCallback()** do not update.

```js
//Parent.js
export default function Parent() {
 const [counter, setCounter] = useState(0);
 const handleClick = () => {
   setCounter(counter + 1);
 };

 const onClick= useCallback(() => { //using useCallback() for the handler function
    console.log("handler");
 }, []);

 console.log("Parent render");
   return (
     <div className="App"><button onClick={handleClick}>Increase</button><h2>{counter}</h2><Child name={"joe"} childHandler={onClick} /></div>
   );
}
```

The **Child** component won’t change.

As we used the **useCallback()** Hook for the **Parent**  **onClick** , it will not be created for each **Parent** rerender, and a memoized instance of the **onClick** will be passed down to the **Child**.

## GitHub reference

For more details, refer to the example for [Memoization in React on the GitHub repository](https://github.com/SyncfusionExamples/React-Memoization/ "Memoization in React demo on GitHub").

## Conclusion

Memoization is a React performance optimization feature that, when utilized correctly, improves application efficiency. To achieve memoization, React provides **PureComponent** , **memo** , **useMemo** , and **useCallback**. Memoization improves performance by saving function results when the same **prop** is provided, minimizing the number of re-renderings.

However, excessive usage of memoization in situations with no performance concerns might deteriorate performance. If we utilize it for all components, performance may suffer because it caches results, increasing the amount of memory the app uses.

So, memoization should only be used when there is a noticeable advantage, and you need to make sure that your app is suitable to use these techniques to get the maximum out of them.

I hope you found this article useful. Thank you for reading!

The [Syncfusion React](https://www.syncfusion.com/react-ui-components "Syncfusion React UI Components") suite offers over 70 high-performance, lightweight, modular, and responsive UI components in a single package. It’s the only suite you’ll ever need to construct a complete app.

If you have questions, you can contact us through our [support forum](https://www.syncfusion.com/forums "Syncfusion support forum"), [support portal](https://support.syncfusion.com/ "Syncfusion support portal"), or [feedback portal](https://www.syncfusion.com/feedback "Syncfusion Feedback Portal"). We are always happy to assist you!