Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use Memoization to improve the performance of React

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article introduces the relevant knowledge of "how to use Memoization to improve the performance of React". In the operation of practical cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

How does React render the view?

Before we discuss the details of Memoization in React, let's take a look at how React renders UI using virtual DOM. [related recommendation: Redis video tutorial]

A regular DOM basically consists of a set of nodes saved in the form of a tree. Each node in the DOM represents a UI element. Whenever a state change occurs in the application, the corresponding nodes of the UI element and all its child elements are updated in the DOM tree, and then the UI redrawing is triggered.

With the help of an efficient DOM tree algorithm, nodes are updated faster, but redrawn slowly, and performance may be affected when the DOM has a large number of UI elements. Therefore, virtual DOM is introduced into React.

This is a virtual representation of the real DOM. Now, whenever there is any change in the state of the application, React does not directly update the real DOM, but instead creates a new virtual DOM. React then compares the new virtual DOM with the previously created virtual DOM, finds the differences, and redraws them.

Based on these differences, virtual DOM can update the real DOM more efficiently. This improves performance because the virtual DOM does not simply update the UI element and all its child elements, but effectively updates only the necessary and minimal changes in the actual DOM.

Why do I need Memoization?

In the previous section, we saw how React uses virtual DOM to effectively perform DOM update operations to improve performance. In this section, we will introduce an example that explains the need to use Memoization to further improve performance.

We will create a parent class that contains a button to increment a variable named count. The parent component also invokes the child component and passes parameters to it. We also added a console.log () statement to the render method:

/ Parent.jsclass Parent extends React.Component {constructor (props) {super (props); this.state = {count: 0};} handleClick = () = > {this.setState ((prevState) = > {return {count: prevState.count + 1};});}; render () {console.log ("Parent render"); return (Increment {this.state.count}) }} export default Parent

The complete code for this example can be seen on CodeSandbox.

We will create a Child class that accepts the parameters passed by the parent component and displays it in the UI:

/ / Child.jsclass Child extends React.Component {render () {console.log ("Child render"); return ({this.props.name});}} export default Child

Every time we click a button in the parent component, the count value changes. Because the state has changed, the render method of the parent component is executed.

The parameters passed to the child component do not change each time the parent component is re-rendered, so the child component should not re-render. However, when we run the above code and continue to increment count, we get the following output:

Parent renderChild renderParent renderChild renderParent renderChild render

You can experience the above example in this sandbox and view the output from the console.

From the output, we can see that when the parent component renders again, the child component will re-render even if the parameters passed to the child component remain the same. This will cause the virtual DOM of the subcomponent to perform a difference check with the previous virtual DOM. Since there are no changes in our subcomponents and no changes in all props when re-rendered, the real DOM will not be updated.

It's really good for performance that a real DOM doesn't update unnecessarily, but we can see that even if there are no actual changes in the subcomponents, a new virtual DOM is created and a difference check is performed. For small React components, this performance consumption is negligible, but for large components, the performance impact is significant. To avoid this difference checking between re-rendering and virtual DOM, we use Memoization.

Memoization in React

In the context of React applications, Memoization is a means that every time the parent component re-renders, the child component will re-render only if the props on which it depends changes. If there is no change in the props on which the subcomponent depends, it does not execute the render method and returns the cached result. Because the rendering method is not performed, there is no virtual DOM creation and difference checking, resulting in a performance improvement.

Now, let's look at how to implement Memoization in class and function components to avoid this unnecessary re-rendering.

Class components implement Memoization

To implement Memoization in a class component, we will use React.PureComponent. React.PureComponent implements shouldComponentUpdate (), which makes a shallow comparison between state and props and re-renders the React component only when props or state changes.

Change the subcomponent to the code shown below:

/ / Child.jsclass Child extends React.PureComponent {/ / here we change React.Component to React.PureComponent render () {console.log ("Child render"); return ({this.props.name});}} export default Child

The complete code for this example is shown in this sandbox.

The parent component remains the same. Now, when we add count to the parent component, the output in the console is as follows:

Parent renderChild renderParent renderParent render

For the first rendering, it calls the render methods of both the parent and child components.

For each re-rendering after the addition of count, only the render function of the parent component is called. Subcomponents do not re-render.

Function component to implement Memoization

To implement Memoization in a function component, we will use React.memo (). React.memo () is a high-level component (HOC) that performs similar work to PureComponent to avoid unnecessary re-rendering.

The following is the code for the function component:

/ / Child.jsexport function Child (props) {console.log ("Child render"); return ({props.name});} export default React.memo (Child); / / here we add HOC to the subcomponents to implement Memoization

At the same time, the parent component is converted to a function component, as follows:

/ / Parent.jsexport default function Parent () {const [count, setCount] = useState (0); const handleClick = () = > {setCount (count + 1);}; console.log ("Parent render"); return (Increment {count});}

The complete code for this example can be seen in this sandbox.

Now, when we increment the count in the parent component, the following will be output to the console:

Problems with Parent renderChild renderParent renderParent renderParent renderReact.memo ()

In the above example, we see that when we use React.memo () HOC on a child component, the child component does not re-render, even if the parent component does.

One small problem to note, however, is that if we pass the function as an argument to the subcomponent, the subcomponent will be re-rendered even after using React.memo (). Let's look at an example like this.

We will change the parent component, as shown below. Here, we add a handler and pass it as an argument to the child component:

/ / Parent.jsexport default function Parent () {const [count, setCount] = useState (0); const handleClick = () = > {setCount (count + 1);}; const handler = () = > {console.log ("handler"); / / the handler function here will be passed to the subcomponent}; console.log ("Parent render"); return (Increment {count});}

The subcomponent code remains intact. We will not use the function passed by the parent component in the child component:

/ / Child.jsexport function Child (props) {console.log ("Child render"); return ({props.name});} export default React.memo (Child)

Now, when we increment the count in the parent component, it will re-render and re-render the child component at the same time, even if there are no changes in the passed parameters.

So, what caused the subcomponents to re-render? The answer is that each time the parent component re-renders, a new handler function is created and passed to the child component. Now, because the handle function is recreated each time you re-render, the subcomponent will notice that the handler reference has changed and re-render the subcomponent when you make a shallow comparison of the props.

Next, we will show you how to solve this problem.

Avoid more repetitive rendering through useCallback ()

The main problem causing the subcomponent to re-render is the re-creation of the handler function, which changes the reference passed to the subcomponent. Therefore, we need a way to avoid this repetitive creation. If the handler function is not recreated, the reference to the handler function does not change, so the child component does not re-render.

To avoid recreating the function every time the parent component is rendered, we will use a React Hook named useCallback (). Hooks was introduced in React 16. To learn more about Hooks, you can check React's official hooks documentation, or check `React Hooks: How to Get Started & Build Your Own ".

The useCallback () hook passes in two parameters: a callback function and a list of dependencies.

The following is an example of useCallback ():

Const handleClick = useCallback (() = > {/ / Do something}, [xQuery])

Here, useCallback () is added to the handleClick () function. The second parameter [x, y] can be an empty array, a single dependency, or a list of dependencies. The handleClick () function is recreated whenever any of the dependencies mentioned in the second parameter change.

If the dependency mentioned in useCallback () has not changed, the Memoization version of the callback function mentioned as the first argument is returned. We will change the parent component to use the useCallback () hook on the handler passed to the child component:

/ / Parent.jsexport default function Parent () {const [count, setCount] = useState (0); const handleClick = () = > {setCount (count + 1);}; const handler = useCallback (() = > {/ / use useCallback () console.log ("handler") for handler functions;}, []); console.log ("Parent render"); return (Increment {count});}

The subcomponent code remains intact.

The complete code for this example is in this sandbox.

When we add count to the parent component of the above code, we can see the following output:

Parent renderChild renderParent renderParent renderParent render

Because we use the useCallback () hook on the handler in the parent component, the handler function is not recreated each time the parent component is re-rendered, and the Memoization version of the handler is passed to the child component. The child component will make a shallow comparison and notice that the reference to the handler function has not changed, so it does not call the render method.

Something worthy of attention.

Memoization is a good means to avoid unnecessary re-rendering of components when the state or props of the component has not changed, thus improving the performance of React applications. You may consider adding Memoization to all components, but this is not necessarily the way to build high-performance React components. Memoization should be used only if the component:

When fixed input has fixed output

With more UI elements, virtual DOM checking will affect performance

Pass the same parameter multiple times

This is the end of "how to use Memoization to improve React performance". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report