Detailed explanation of performance optimization ideas for React functional components

Detailed explanation of performance optimization ideas for React functional components

Optimization ideas

There are two main optimization directions:

  1. Reduce the number of re-renders. Because the heaviest (longest-time-consuming) part in React is reconciliation (which can be simply understood as diff). If you don’t render, there will be no reconciliation.
  2. Reduce the amount of calculation. The main purpose is to reduce repeated calculations. For functional components, each render will execute the function call from the beginning.

When using class components, the React optimization APIs used are mainly: shouldComponentUpdate and PureComponent

So how do we optimize performance in functional components? The following methods are mainly used to optimize

  • React.memo
  • useCallback
  • useMemo

React.memo

Let’s look at an example:

We put a button in the parent component to modify the subtitle and introduce the Child subcomponent

As you can see, the first time the subcomponent comes in, it prints console.log('I am a subcomponent')

When you click to modify the subtitle, the Child component is also printed, resulting in unnecessary repeated rendering times.

//Parent component import {useState} from 'react'

import Child from "./Child";
const Index = ()=>{
    const [subTitle, setSubTitle] = useState('I am a subtitle')
    const updateSubTitle = ()=>{
      setSubTitle('Modify subtitle')
    }
    return (
      <div>
        <div>Functional component performance optimization</div>
        <div>{subTitle}</div>
        <button onClick={updateSubTitle}>Modify subtitle</button>
        <Child/>
      </div>
    );
  }
  
  export default Index;


//Child component Child.js
const Child = ()=>{
    console.log('I am a child component')
    return (
        <div>I am a child component</div>
    )
}
export default Child

Optimize it and use React.memo to wrap the subcomponent

import React from "react";

const Child = ()=>{
    console.log('I am a child component')
    return (
        <div>I am a child component</div>
    )
}
export default React.memo(Child)

Observe again and find that the Child subcomponent is not rendered repeatedly

useCallback

Here we modify it again, add an onclick event to the Child subcomponent, and then click the modify subtitle button, and find that our Child subcomponent is re-rendered. This is mainly because the handlerClick function re-renders the changes when modifying the subtitle, causing the subcomponent to re-render.

// Parent component const Index = ()=>{
    const [subTitle, setSubTitle] = useState('I am a subtitle')
    const updateSubTitle = ()=>{
      setSubTitle('Modify subtitle')
    }
    const handlerClick = ()=>{
      console.log('subcomponent click')
    }
    return (
      <div>
        <div>Functional component performance optimization</div>
        <div>{subTitle}</div>
        <button onClick={updateSubTitle}>Modify subtitle</button>
        <Child onClick={handlerClick}/>
      </div>
    );
  }

//Child subcomponent const Child = (props)=>{
    console.log('I am a child component')
    return (
        <div>
            <div>I am a child component</div>
            <button onClick={props.onClick}>Subcomponent button</button>
        </div>
    )
}
export default React.memo(Child)

To optimize, use useCallback to wrap the handlerClick function of the child component, click updateSubTitle again to modify the subtitle, and find that the Child subcomponent is not re-rendered

// Parent component const Index = ()=>{
    const [subTitle, setSubTitle] = useState('I am a subtitle')
    const updateSubTitle = ()=>{
      setSubTitle('Modify subtitle')
    }
    const handlerClick = useCallback(()=>{
      console.log('subcomponent click')
    },[])

    return (
      <div>
        <div>Functional component performance optimization</div>
        <div>{subTitle}</div>
        <button onClick={updateSubTitle}>Modify subtitle</button>
        <Child onClick={handlerClick}/>
      </div>
    );
  }
  
  export default Index;

Here is the usage of useCallback

const callback = () => {
  doSomething(a, b);
}

const memoizedCallback = useCallback(callback, [a, b])

Pass the function and dependencies as parameters to useCallback, which will return a memoized version of the callback function. This memoizedCallback will only be updated when the dependencies change.

useMemo

useMemo is used to cache calculation results

Let's take a look at an example. We add a calcCount calculation function based on the previous one, and then click updateSubTitle to update the subtitle. We find that calcCount is recalculated, which means that each rendering will cause repeated calculations. If the amount of calculation is large, it will greatly affect the performance.

// Parent component const Index = ()=>{
    const [subTitle, setSubTitle] = useState('I am a subtitle')
    const updateSubTitle = ()=>{
      setSubTitle('Modify subtitle')
    }
    const handlerClick = useCallback(()=>{
      console.log('subcomponent click')
    },[])

    const calcCount = ()=>{
      
      let totalCount = 0
      for(let i=0;i<10000;i++){
        totalCount+=i
      }
      console.log('totalCount',totalCount)
      return totalCount
    }

    const count = calcCount()

    return (
      <div>
        <div>Functional component performance optimization</div>
        <div>{subTitle}</div>
        <button onClick={updateSubTitle}>Modify subtitle</button>
        <div>count:{count}</div>
        <Child onClick={handlerClick}/>
      </div>
    );
  }

Optimize it and use useMemo to cache the calculation results. Click the updateSubTitle button again to modify the subtitle. You can find that the calcCount function no longer repeats the calculation.

 const calcCount = ()=>{
      
      let totalCount = 0
      for(let i=0;i<10000;i++){
        totalCount+=i
      }
      console.log('totalCount',totalCount)
      return totalCount
    }

    const count = useMemo(calcCount,[])

Finally, it should be noted that useMemo cannot be used blindly. It should be used according to specific scenarios. For example, if the amount of data calculation is relatively large, then it is more applicable. For some ordinary calculations that are worth calculating, it can be ignored, because useMemo itself will also consume some performance. Blind use will be counterproductive.

References

https://mp.weixin.qq.com/s/YGvmSrr-yhPUNHbwlLSFsA

http://www.ptbird.cn/react-hook-useMemo-purerender.html

This is the end of this article about performance optimization of React functional components. For more relevant React performance optimization content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • How to add typescript type hints to react component library
  • In-depth understanding of react component types and usage scenarios
  • React's implementation method of passing class names to child components through parent components
  • Do you know the difference between React functional components and class components?

<<:  MySql 5.7.20 installation and configuration of data and my.ini files

>>:  Forever+nginx deployment method example of Node site

Recommend

Detailed explanation of the simple use of MySQL query cache

Table of contents 1. Implementation process of qu...

js code that associates the button with the enter key

Copy code The code is as follows: <html> &l...

Full steps to create a password generator using Node.js

Table of contents 1. Preparation 2. Writing comma...

Detailed explanation of the code for implementing linear gradients with CSS3

Preface The gradient of the old version of the br...

CSS positioning layout (position, positioning layout skills)

1. What is positioning? The position attribute in...

Vertical and horizontal splitting of MySQL tables

Vertical Split Vertical splitting refers to the s...

How to use mysqladmin to get the current TPS and QPS of a MySQL instance

mysqladmin is an official mysql client program th...

Docker implements container port binding local port

Today, I encountered a small problem that after s...

HTTP Status Codes

This status code provides information about the s...

JavaScript uses promise to handle multiple repeated requests

1. Why write this article? You must have read a l...

CentOS 7 cannot access the Internet after modifying the network card

Ping www.baidu.com unknown domain name Modify the...