1. React performance optimization
- To reduce to
render
The number of times. - Reduce the amount of computation. The main thing is to reduce double counting, for functional components, each time
render
All function calls are executed from scratch.
- Using a class component
(class)
When usedReact
The optimization API is mainly:shouldComponentUpdate
εPureComponent
, all in order to reduce rerender
The number of times that the parent component updates and the child component updates.
2. Optimization method of function components
2.1 React.memo (reduce the number of render times)
You can reduce the number of times you rerender a PureComponent.
Take a simple π° :
- Modifying the parent componenttitleIs passed to the child component simultaneouslynameValue.
Import React, {useState} from "React "; import ReactDOM from "react-dom"; Import Child from './ Child 'function Father() {const [title, setTitle] = useState(" parent title"); return ( <div className="Father"> <h1>{ title }</h1> <button onClick={() => SetTitle (" parent component's title changed ")}> Modify parent component's title</button> <Child name=" parent component's value "></Child> </div>); } const rootElement = document.getElementById("root"); ReactDOM.render(<Father />, rootElement);Copy the code
// subcomponent import React from "React "; function Child(props) { console.log(props.name) return <p>{props.name}</p> } export default Child;Copy the code
- The first render looks like this:
- And it prints on the console“Value passed from parent component to child component”,
Child
The component is rendered. - Next click on the title button of the parent component and the page will become:
- Visible to the parent component
title
It has changed, and the console is printing again“Value passed from parent component to child component”. Child components in theprops
Without changing the case, render again. If the sub-component is very large, rendering at a time will consume a lot of performance, we should minimize the rendering of this component, otherwise it is prone to performance problems.
React. Memo renders the same results given the same props, and improves the performance of components by memorizing the results of component rendering. The above example can then be modified as follows:
// subcomponent import React from "React "; function Child(props) { console.log(props.name) return <p>{props.name}</p> } export default React.memo(Child); // Use react.memo ()Copy the code
2.2 useCallback (reduce the number of render times)
Following the example above, modify the requirement again. Add a subtitle and a button that changes the subtitle to the parent component, and put the button that changes the title into the child component.
Import React, {useState} from "React "; import ReactDOM from "react-dom"; import Child from "./child"; Function Father() {const [title, setTitle] = useState(); function Father() {const [title, setTitle] = useState(); Const [subtitle, setSubtitle] = useState(" parent subtitle "); Const callback = () => {setTitle(" parent component's title changed "); }; return ( <div className="Father"> <h1>{title}</h1> <h2>{subtitle}</h2> <button onClick={() => SetSubtitle (" Parent subtitle changed ")}> Modify parent subtitle </button> <Child onClick={callback} name= } const rootElement = document.getElementById("root"); ReactDOM.render(<Father />, rootElement);Copy the code
// subcomponent import React from "React "; function Child(props) { console.log(props.name); Return (<div> <button onClick={props. OnClick}> modify parent component title</button> <h1>{props. Name}</h1> </div>); } export default React.memo(Child);Copy the code
- The first render looks like this:
-
And the console prints “value passed from parent to Child”, indicating that the Child component is rendered.
-
Next, click the button to modify the subtitle of the parent component, and the page will become:
- You can see that the subtitle of the parent component has changed, and the console again prints the value passed from parent to child. The subcomponent is rendered again with the props unchanged. But there is no change in the subcomponent, so the re-rendering of the subcomponent is superfluous, why is it re-rendered?
A component can be rerendered in one of three ways:
- The state of the component itself changes;
- The parent component rerenders, causing the child component to rerender, but the parent component
props
There is no change; - The parent component rerenders, causing the child component to rerender, but passed by the parent
props
Changed;
The first rule is that clicking to modify the subtitle does not change the state of the child component.
The parent component was re-rendered. The props passed by the parent component to the child component did not change, but the child component was re-rendered. We used React.
When the parent component is rendering again, the props passed to the child component is changed, and the two properties passed to the child component are name and onClick. The name is a constant. Why does the callback passed to onClick change? As stated at the beginning of this article, each time a function component is re-rendered, the function component is re-executed from the beginning, so the callback function created on both times must have changed, causing the child component to re-render.
UseCallback keeps the references of the two functions the same when the function is not changed, so the above example can be modified as follows:
Import React, {useState, useCallback} from "React "; import ReactDOM from "react-dom"; import Child from "./child"; Function Father() {const [title, setTitle] = useState(); function Father() {const [title, setTitle] = useState(); Const [subtitle, setSubtitle] = useState(" parent subtitle "); Const callback = () => {setTitle(" parent component's title changed "); }; Const _callback = useCallback(callback, []); const _callback = useCallback(callback, []); return ( <div className="Father"> <h1>{title}</h1> <h2>{subtitle}</h2> <button onClick={() => SetSubtitle (" Parent subtitle changed ")}> Modify parent subtitle </button> <Child onClick={_callback} name= } const rootElement = document.getElementById("root"); ReactDOM.render(<Father />, rootElement);Copy the code
2.3 useMemo (Reduce the amount of computation)
UseMemo is mainly used to cache the results of functions that require a lot of computation, so it can avoid unnecessary double computations. It has a similar effect with computed data in Vue and can reduce the amount of computation.
import React, { useState } from "react"; function App() { const [num, setNum] = useState(0); Function resultFn() {let result = 0; for (let i = 0; i < 10000; i++) { result += i; } console.log(result) // 49995000 return result; } const resultNum = resultFn(); Return (<div className="App"> <h1>count: {num}</h1> <button onClick={() => setNum(num + resultNum)}>+1</button> </div> ); }Copy the code
If we change I to 10000000, every time we click the +1 button, we will re-render and get the same result, which will have some impact on performance, we can make the following changes:
import React, { useState, useMemo } from "react"; function App() { const [num, setNum] = useState(0); Function resultFn() {let result = 0; for (let i = 0; i < 10000; i++) { result += i; } console.log(result) // 49995000 return result; } const resultNum = useMemo(resultFn, []); // useMemo return (<div className="App"> <h1>count: {num}</h1> <button onClick={() => setNum(num + resultNum)}>+1</button> </div> ); }Copy the code
Two points to note:
If no dependency array is provided, useMemo computs the new value every time it renders.
2. If the calculation function is very small, you can choose not to use useMemo to avoid other problems caused by improper use;
For more tech sharing please follow my personal blog β€www.chengxiaohui.cn β€