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

In-depth understanding of this in JavaScript

In-depth understanding of this in Js JavaScript s...

Windows Server 2016 Standard Key activation key serial number

I would like to share the Windows Server 2016 act...

How to Understand and Identify File Types in Linux

Preface As we all know, everything in Linux is a ...

Detailed process of building nfs server using Docker's NFS-Ganesha image

Table of contents 1. Introduction to NFS-Ganesha ...

Analyze the compilation and burning of Linux kernel and device tree

Table of contents 1. Prepare materials 2. Downloa...

Detailed steps to install the specified version of docker (1.12.6) using rpm

1. Reasons If the system is Centos7.3, the Docker...

Summary of Linux system user management commands

User and Group Management 1. Basic concepts of us...

Several situations that cause MySQL to perform a full table scan

Table of contents Case 1: Case 2: Case 3: To summ...

vue.config.js packaging optimization configuration

The information on Baidu is so diverse that it...

MySQL 8.0.18 Installation Configuration Optimization Tutorial

Mysql installation, configuration, and optimizati...

jQuery implements ad display and hide animation

We often see ads appear after a few seconds and t...

HTML 5.1 learning: 14 new features and application examples

Preface As we all know, HTML5 belongs to the Worl...