React.memo 和 useMemo 的使用问题小结

 更新时间:2022年11月04日 15:10:28   作者:前端小二哥  
随着代码的增加,每次的状态改变,页面进行一次 reRender ,这将产生很多不必要的 reRender 不仅浪费性能,从而导致页面卡顿,这篇文章主要介绍了React.memo 和 useMemo 的使用问题小结,需要的朋友可以参考下

问题背景

大家在使用 React 框架进行开发时一定遇到过以下问题:

  • 当函数式组件中的某一状态改变,整个组件刷新,重新渲染
  • 在类组件中 setState() 时,整个组件也会重新渲染
  • 以上问题若不进行优化,导致的结果是:
  • 随着代码的增加,每次的状态改变,页面进行一次 reRender ,这将产生很多不必要的 reRender 不仅浪费性能,从而导致页面卡顿;

useMemo 进行优化

以下面 App 组件进行分析

import './App.css';
import ProfileTest from './components';
import { Profiler, useEffect, useMemo, useState, useRef } from 'react'
function App () {
  const [name, setName] = useState('')
  const [num, setNum] = useState(0)
  useEffect(() => {
    setTimeout(() => {
      console.log('111')
      setName('xxx')
    }, 2000)
  }, [])
  const memoVal = useMemo(() => {
    console.log('运行了useMemo num值为:', num);
    return num + 1
  }, [num])
  console.log('memoVal值为:', memoVal)
  console.log('父组件运行分割线----------------------------------------------------')
  const changeNum = () => {
    setNum(2)
  }
  return (
    <Profiler id='profile-test'>
      <div className="App">
        {/* <ProfileTest /> */}
        <button style={{ marginTop: 100 }} onClick={changeNum}>改变num</button>
      </div>
    </Profiler>
  );
}
export default App;

以上组件在首次渲染、以及 2秒后的执行结构如下图所示:

很显然首次渲染执行了,useMemo,而2秒后有状态变化后没有执行useMemo。
点击按钮改变 useMemo 的依赖项后可以发现,如下图所示 useMemo 又执行了。

因此在使用函数式组件时,可以使用 useMemo 减少不必要的reRender 提高组件的性能;

React.memo 进行优化

在以上组件的基础上,给App 增加一个子组件,代码如下所示:

import React from 'react'

export default function Children(props) {
  console.log('子组件运行了,接收的props是', props)
  console.log('子组件渲染分割线------------------------------------------')
  return <div>子组件</div>
}

首次render 以及 2s后组件的 reRender 控制台打印结果如下图所示:

由上图可以看出,reRender 时Children 组件的props并未变化,因此,此次Children 组件的reRender 是不必要的,需要进行优化;

props的值是基本类型

如果 Children 的 props 是基本类型,则可以做一下优化:

import React, { memo } from 'react'

function Children(props) {
  console.log('子组件运行了,接收的props是', props)
  console.log('子组件渲染分割线------------------------------------------')
  return <div>子组件</div>
}
export default memo(Children)

优化后控制台打印如下信息,一下信息可以看出 Children 组件没有进行 reRender

props的值是引用类型

若子组件的 props 是引用类型 ,则需要进行深度比较,此时React.memo()要传入第二个参数进行深度比较,改变后 Children 组件的代码如下所示:

import React, { memo } from 'react'

function Children(props) {
  console.log('子组件运行了,接收的props是', props)
  console.log('子组件渲染分割线------------------------------------------')
  return <div>子组件</div>
}
export default memo(Children, (preProps, nextProps) => {
  return JSON.stringify(preProps) === JSON.stringify(nextProps)
})

以上 memo 第二个参数 ,通过比较 preProps 和 nextProps 返回一个布尔值,使得props 进行深度比较;
注意:React.memo的第二个参数进行深度比较时有一定开销,其产生的开销存在大于子组件reRender的可能

写在最后

useMemo() 和 React.memo() 都是进行组件性能优化的方式,其区别是

  • useMemo 可以进行更加细粒度的优化(有依赖项)
  • React.memo() 可以控制props的浅比较和深度比较
  • React.memo在没有第二个参数的时候相当于class中的PureComponent,当增加了第二个参数的时候相当于生命周期中的shouldComponentUpdate;

到此这篇关于React.memo 和 useMemo 的使用问题小结的文章就介绍到这了,更多相关React.memo 和 useMemo内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • ahooks useInfiniteScroll源码解析

    ahooks useInfiniteScroll源码解析

    这篇文章主要为大家介绍了ahooks useInfiniteScroll源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • 详解React Native 采用Fetch方式发送跨域POST请求

    详解React Native 采用Fetch方式发送跨域POST请求

    这篇文章主要介绍了详解React Native 采用Fetch方式发送跨域POST请求,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • react时间分片实现流程详解

    react时间分片实现流程详解

    实现react时间分片,主要内容包括什么是时间分片、为什么需要时间分片、实现分片开启 - 固定、实现分片中断、重启 - 连续、分片重启、实现延迟执行 - 有间隔、时间分片异步执行方案的演进、时间分片简单实现、总结、基本概念、基础应用、原理机制和需要注意的事项等
    2022-11-11
  • React实现点击删除列表中对应项

    React实现点击删除列表中对应项

    本文主要介绍了React 点击删除列表中对应项的方法。具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • 详解React中key的作用

    详解React中key的作用

    这篇文章主要介绍了React中key的作用,帮助大家更好的理解和学习使用React,感兴趣的朋友可以了解下
    2021-04-04
  • 40行代码把Vue3的响应式集成进React做状态管理

    40行代码把Vue3的响应式集成进React做状态管理

    这篇文章主要介绍了40行代码把Vue3的响应式集成进React做状态管理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • React Hooks - useContetx和useReducer的使用实例详解

    React Hooks - useContetx和useReducer的使用实例详解

    这篇文章主要介绍了React Hooks - useContetx和useReducer的基本使用,本文通过实例代码给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-11-11
  • 基于react后端渲染模板引擎noox发布使用

    基于react后端渲染模板引擎noox发布使用

    本篇文章主要介绍了基于react后端渲染模板引擎noox发布使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • create-react-app修改为多页面支持的方法

    create-react-app修改为多页面支持的方法

    本篇文章主要介绍了create-react-app修改为多页面支持的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • React项目打包发布到Tomcat页面空白问题及解决

    React项目打包发布到Tomcat页面空白问题及解决

    这篇文章主要介绍了React项目打包发布到Tomcat页面空白问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06

最新评论