react17: summary of memo, useMemo and useCallback usage

        The main thing React does is keep our  UI in sync  with our  state  , and to synchronize them, we need to perform an operation called "re-render". Essentially, useMemo and  useCallback are both tool Hooks used to help us optimize  re-rendering  . They achieve optimization results in the following two ways.

  • Reduce the amount of work that needs to be done in one render.

  • Reduce the number of times a component needs to be re-rendered.

  • memo : Use  React.memo a wrapped component to tell React that this is a pure component to protect it from irrelevant state updates, that is, it will only be re-rendered when new data (props) is received or the internal state changes.
  • useMemo : (1) Scenarios that require a large amount of calculations: cache calculation results (similar to calculated properties in vue); (2) Reference retention: retain a reference to a complex type (such as a specific array/object variable and other complex types, non- basic data types).
  • useCallback : (1) Reference retention: retain a reference to a function.

        Note: useMemo and  useCallback are the same thing, just replace the return value from array/object to function. useCallback It is a kind of syntactic sugar. It exists purely to make it easier for us to cache callback functions.

Preface: In a parent component, every time the state         in the parent component changes (modified using setState), the re-rendering of the parent component will be triggered, which will also cause all child components to be re-rendered.

1. memo

Syntax: memo(function component, (prevProps, props) => { ... return Boolean value}) , the second parameter is the comparison method of the values ​​​​of before and after props, to determine whether the props have changed, the default is shallow comparison, when true is returned , render will not be triggered, and render will be triggered when false is returned.

Problems used to solve: (1) The child component does not have any props, but each rendering of the parent component will also cause the child component to be re-rendered. (2) The child component has basic data type props, and the props values ​​have not changed. Rendering of the parent component will also cause the child component to be re-rendered.

import { memo } from 'react';
const PureComponentChild = () => {
  return (
    ...
  )
}
// 使用memo包裹:只有props或自身的状态更改时,组件才会渲染。
export default memo(PureComponentChild)

Small extension: In the parent component: (1) Reference type props variables: use useState declaration (memo takes effect), use ordinary variable declaration in the component (memo does not take effect, cause of the problem: new reference problem is regenerated each time rendering), in Ordinary reference variables declared outside the function component (memo takes effect). (2) Basic data type props variables: The above three writing methods, memo will take effect (that is, the sub-components will be cached and will not be rendered repeatedly) (3) In a certain function, call setState twice to modify the two variable values ​​​​in the parent component , and finally the parent component is only rendered once.

2. useMemo

Syntax: useMemo(() => { return complex type variable value or function}, [dependent variable array] ) , return value: any variable

Problems used to solve: (1) The child component is wrapped with memo, but the props received are "unchanged" (reference type props, such as variables such as objects, arrays, and functions). At this time, the rendering of the parent component will still cause The component re-renders. The reason for the problem: complex types, each time the parent component is rendered, a new reference will be generated. (2) The calculation result of a certain logical processing that performs a large number of calculations will be recalculated every time it is rendered, which consumes performance.

Subassembly: 

import { useMemo, memo } from 'react'
// props: 接收一个引用类型 list
const ChildA = ({ list }) => {
   return (
      list.map((item) => {
        return <h1 key={item.name}>{item.name}</h1>;
      });
  )
}
export default memo(ChildA)

Parent component:

import ChildA from './components/ChildA';
import { useMemo, useState } from 'react';
import { Button } from 'antd'

// 父组件
const ParentCom = () => {
  const [name, setName] = useState('这是父组件默认名');
  // 写法1:直接在父组件中声明复杂类型变量,父组件渲染 -》子组件也会重新渲染。
  // const list = [{ name: '小明' }, { name: '小花' }];
  // 写法2:使用useMemo包裹,依赖数组为空,父组件渲染 -》 子组件不会重新渲染(除非依赖数组中变量的值改变)。
  const list = useMemo(() => {
    return [{ name: '小明' }, { name: '小花' }];
  }, []);

  const modifyName = () => {
    setName('新名' + Date.now());
  };

  return (
    <>
      <h1>父组件名: {name}</h1>
      <Button onClick={modifyName} />
      <ChildA list={list} />;
    </>
  );
};
export default ParentCom;

三、useCallback

Syntax: useCallback(() => {Processing logic inside the function}, [Dependent variable array]) , return value: is a function (reference).

Problems used to solve: (1) The child component is wrapped in memo, and the props have passed functions. Every time the parent component is updated, even if the function does not change, the problem will be re-rendered.

import { useCallback, useMemo } from 'react'

// useCallback方式
const modifyParentNameFun = useCallback(() => {
   ... // 函数内部自定义处理逻辑
},[])

// useMemo方式:跟使用useCallback是等效的,一样的功能!2者选一即可!
const modifyParentNameFun = useMemo(() => {
   return function() [
    ... // 函数内部自定义处理逻辑
   }
},[])

<ChildA modifyParentNameFun={modifyParentNameFun}>

Reference URL:

Guess you like

Origin blog.csdn.net/qq_38969618/article/details/130748768