Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for What is Memoization in React?
Syncfusion, Inc. profile imageSuresh Mohan
Suresh Mohan forSyncfusion, Inc.

Posted on • Originally published atsyncfusion.com on

     

What is Memoization in React?

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 offersmemoization 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 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 useReact.PureComponent within class components. Memoization for functional components is also possible withReact.memo() HOC anduseMemo() Hook. TheuseCallback() 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 implementsReact.ShouldComponentUpdate(), which performs a shallow comparison ofstate andprops and only renders the React component if theprops orstate have changed.

In this case, we have to keep the props and state as simple as possible. SincePureComponent may yield incorrect results if they include any advanced data structures. AsPureComponent’s shouldComponentUpdate() avoidsprop updates for the entire component subtree, we should also ensure that allPureComponent’s children are alsoPureComponent.

Refer to the following simple example to implement memoization withReact.PureComponent.

//Parent.jsimportReact,{Component}from'react';importChildfrom'./Child';classParentextendsReact.Component{constructor(props){super(props);this.state={count:0};}onClick=()=>{this.setState((prevState)=>{return{count:prevState.count+1};});};render(){console.log("Parent render");return(<divclassName="App"><buttononClick={this.onClick}>UpdateCounter</button> <h2>{this.state.count}</h2><Childname={"child"}/></div>);}}exportdefaultParent;
Enter fullscreen modeExit fullscreen mode

TheChild component should be like this.

//Child.jsimportReact,{Component,PureComponent}from'react';classChildextendsReact.PureComponent{render(){console.log("Child render");return(<div><h2>{this.props.name}</h2></div>);}}exportdefaultChild;
Enter fullscreen modeExit fullscreen mode

When you click on theUpdate Counter in theParent component, it will call both theParent andChild components’ render methods for the initial render.

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

How to implement memoization in Functional Components

Let’s see how to useReact.memo() anduseMemo() for memoization under this section.

React.memo()

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

Consider these two components. TheParent component will look like this.

constParent=()=>{const[counter1,setCounter1]=React.useState(0)const[counter2,setCounter2]=React.useState(0)constincrementCounter1=()=>{setCounter1(counter1=>counter1+1)}return(<><buttononClick={incrementCounter1}>Incrementcounter1</button><Child value={counter1}>Counter 1</Child><Childvalue={counter2}>Counter2</Child></>)}
Enter fullscreen modeExit fullscreen mode

And theChild component is as follows.

constChild=({value,child})=>{console.log('Render:',child)return(<div>{child}:{value}</div>)}exportdefaultChild;
Enter fullscreen modeExit fullscreen mode

The state ofcounter1 Child component updates whenever the user clicks theIncrement counter 1 button, leading theParent to rerender bothcounter Child components , which can be considered an undesired rerender.

You need to wrap theChild component withReact.memo() to avoid this. It will only force theChild component to rerender if theprops are changed.

constChild=({value,child})=>{console.log('Render:',child)return(<div>{child}:{value}</div>)}exportdefaultReact.memo(Child)
Enter fullscreen modeExit fullscreen mode

Note: If the component has auseState ,useReducer , oruseContext Hook, the state or context will still trigger a rerender.

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

functionApp(props){/* render using props */}functionareEqual(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   */}exportdefaultReact.memo(App,areEqual);
Enter fullscreen modeExit fullscreen mode

useMemo()

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

To useuseMemo(), 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.

constmemoizedValue=useMemo(()=>expensiveComputation(a,b),[a,b])
Enter fullscreen modeExit fullscreen mode

Let’s consider a simple example for calculating a factorial. When the component renders initially, theuseMemo Hook callsFactorialCalc 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 thememoizedFactorial instead of callingFactorialCalc.

import{useState,useMemo}from"react";constApp=()=>{const[number,SetNumber]=useState(1);constmemoizedFactorial=useMemo(()=>FactorialCalc(number),[number]);constonChange=(e)=>{console.log(e.target.value);SetNumber(Number(e.target.value));};return(<div><inputtype="text"onChange={onChange}/>{memoizedFactorial}</div>);};functionFactorialCalc(n){console.log('factorialOf(n) called!');returnn<=0?1:n*FactorialCalc(n-1);}exportdefaultApp;
Enter fullscreen modeExit fullscreen mode

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

useCallback()

useCallback() is almost equivalent touseMemo() 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 theReact.memo() in the child component in the previous case, theChild component did not rerender, although theParent component did. Nevertheless, passing a function as a prop to aChild component would still cause theChild component to rerender, even withReact.memo().

Consider the following example.

//Parent.jsexportdefaultfunctionParent(){const[counter,setCounter]=useState(0);consthandleClick=()=>{setCounter(counter+1);};constonClick=()=>{console.log("onClick");// This is the new handler that will be passed to the child};console.log("Parent render");return(<divclassName="App"><buttononClick={handleClick}>Increase</button><h2>{counter}</h2><Childname={"child"}childHandler={onClick}/></div>);}
Enter fullscreen modeExit fullscreen mode

And theChild component will look like this.

//Child.jsexportfunctionChild(props){console.log("Child render");return(<div><h2>{props.name}</h2></div>);}exportdefaultReact.memo(Child);
Enter fullscreen modeExit fullscreen mode

Even when theprops provided haven’t changed, when we increase thecounter in theParent component, it rerenders theChild component, as well.

So, what triggers theChild component to rerender is that a newonClick function is generated and sent to theChild component each time theParent component rerenders. Because theonClick function is created with each rerender, theChild detects that theonClick reference has updated and rerenders theChild component solely on a basic comparison ofprops.

TheuseCallback helps us to prevent recreating the method each time the parent component is rendered. We have to introduce theuseCallback() Hook to theonClick 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 inuseCallback() do not update.

//Parent.jsexportdefaultfunctionParent(){const[counter,setCounter]=useState(0);consthandleClick=()=>{setCounter(counter+1);};constonClick=useCallback(()=>{//using useCallback() for the handler functionconsole.log("handler");},[]);console.log("Parent render");return(<divclassName="App"><buttononClick={handleClick}>Increase</button><h2>{counter}</h2><Childname={"joe"}childHandler={onClick}/></div>);}
Enter fullscreen modeExit fullscreen mode

TheChild component won’t change.

As we used theuseCallback() Hook for theParentonClick , it will not be created for eachParent rerender, and a memoized instance of theonClick will be passed down to theChild.

GitHub reference

For more details, refer to the example forMemoization in React on the GitHub repository.

Conclusion

Memoization is a React performance optimization feature that, when utilized correctly, improves application efficiency. To achieve memoization, React providesPureComponent ,memo ,useMemo , anduseCallback. Memoization improves performance by saving function results when the sameprop 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!

TheSyncfusion React 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 oursupport forum,support portal, orfeedback portal. We are always happy to assist you!

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Syncfusion provides third-party UI components for React, Vue, Angular, JavaScript, Blazor, .NET MAUI, ASP.NET MVC, Core, WinForms, WPF, UWP and Xamarin.

More fromSyncfusion, Inc.

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp