useMemo、useCallback、memo 三者简单使用

81 阅读3分钟

useMem、useCallback、memo官方介绍

大家都知道 useMemo、useCallback、memo的主要功能是性能优化。下面先看一下官方文档中的解释

useMemo

图片.png

useCallback

图片.png

memo

图片.png 图片.png

useMemo、useCallback、memo个人简单理解

useMemo和useCallback

  他们各自具体的用途我就不多做介绍了,在上面的官方文档中说的很具体。下面简单说一下我的理解.

  • useMemo和useCallback是两个方法,这两个方法都接收两个参数:1.一个函数 2.含有依赖值的数组。这两个方法都有一个返回值。

  • 他们的第二个参数的作用和目的是一样的:「第一个参数是否会执行都会根据后面的依赖项来进行判断,如果依赖项中的值发生改变了才会执行第一个函数」。

  • useMemo的第一个参数「函数」 函数体会返回一个处理后的数据,返回的数据是页面渲染的时候使用的数据(useMemo的这个方法和vue的computed类似,useMemo将一个值进行处理然后返回一个新的值[返回的新的值是一个记忆值 如果第二个参数「依赖项」不改变就返回上一次的记忆值])

  • useCallback会将第一个参数「函数」返回,这个函数返回一个记忆函数(返回的函数是一个记忆函数 如果第二个参数「依赖项」不改变就返回上一次的函数

memo

   使用memo包裹的组件,如果props中的值没有发生改变那么该组件就不会重新渲染。memo的这个使用效果和class组件中使用的shouldComponentUpdate和PureComponent类似

useMemo、useCallback、memo 具体使用例子

index.tsx文件(父组件文件)

import React, { useCallback, useMemo, useState } from 'react';
import { Col, Row, Button } from 'antd';
import Works from './works';

const Index = () => {
  const [year, setYear] = useState(0);
  const [position, setPosition] = useState('初级开发工程师');
  const defaultWangAge = 17;

  const addYear = () => {
    setYear(year + 1);
  };

  const getAge = useMemo(() => {
    console.log('age重新渲染');
    return defaultWangAge + year;
  }, [year]);

  const getPosition = () => {
    console.log('position重新渲染');
    return position;
  };

  const changePosition = () => {
    if (year >= 0 && year < 2) {
      setPosition('中级开发工程师');
    } else {
      setPosition('高级开发工程师');
    }
  };

  const resetPosition = useCallback(() => {
    setPosition('初级开发工程师');
  }, [position]);

  // const resetPosition = () => {
  //   setPosition('初级开发工程师')
  // }

  return (
    <Row>
      <Col span={24}>
        <h2>{year}年</h2>
        <h3>小王</h3>
        <h3>年龄:{getAge}</h3>
        <Button type="primary" onClick={addYear}>
          年份 + 1
        </Button>
      </Col>
      <Col span={24}>
        <h3>职位:{getPosition()}</h3>
        <Button type="primary" onClick={changePosition}>
          切换职位
        </Button>
      </Col>
      <Works resetPosition={resetPosition} />
    </Row>
  );
};
export default Index;

works.tsx文件(子组件文件)

import React, { memo } from 'react';
import { Col, Row, Button } from 'antd';

interface propsTypes {
  resetPosition?: ((event: any) => void) | undefined;
}

const Works = ({ resetPosition }: propsTypes) => {
  console.log('工作区组件重新渲染。。。。。。。');
  return (
    <Row style={{ margin: 24, background: '#f2f2f2', width: '100%' }}>
      <Col>
        <h2>子组件页面</h2>
        <Button type="primary" onClick={resetPosition}>
          职位重置
        </Button>
      </Col>
    </Row>
  );
};
export default memo(Works);

使用效果

图片.png

  • 页面刷新控制台展示

图片.png

  • 点击年份+1时 控制台打印结果(age和position由于页面刷新在控制台进行打印,子组件没有重新渲染)

图片.png

  • 点击切换职位时 控制台打印结果(position和子组件进行了重新渲染,由于age没有发生改变所以age相关的部分没有发生重新渲染, 由于子组件中的useCallback中依赖的position发生改变了,所以也进行更新了)

图片.png

  • 页面刷新后,直接点击位置重置 控制台打印结果(在子组件触发按钮点击时,position和age都没有发生改变 都没有重新渲染)

图片.png

  • 页面刷新后,点击「修改职业」后再点击「职位重置」(开始点击修改职位后position发生了改变,接下来点击重置也改变了position所以position方法和子组件都重新执行了,而age没有发生改变所以在重新渲染的时候没有执行)

图片.png