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

目录
  • 问题背景
  • useMemo 进行优化
  • React.memo 进行优化
    • props的值是基本类型
    • props的值是引用类型
  • 写在最后

问题背景

大家在使用 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内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • react组件memo useMemo useCallback使用区别示例

    目录 正文 memo使用 useMemo使用 useCallback使用 正文 memo用来优化函数组件的重复渲染行为,针对的是一个组件 useMemo返回一个memoized的值 本质都是用同样的算法来判定依赖是否发生改变,继而决定是否触发memo或者useMemo中的逻辑,利用memo就可以避免不必要的重复计算,减少资源浪费 useCallback返回一个memoized的函数 useMemo和useCallback都接收两个参数,第一个参数为fn,第二个参数为[],数组中是变化依赖的参数

  • 解析react 函数组件输入卡顿问题 usecallback react.memo

    目录 现象 分析 解决 方案一: 方案二: 弊端 现象 在输入问题时,输入框响应巨慢. 效果图 分析 右侧控制台显示,子组件不停在mount unmount,子组件中使用了CKEditor组件,每次mount开支较大,导致输入卡顿 代码如下: const qdata = (q.qdata || [ { id: getQuestionId('OPTION') }, { id: getQuestionId('OPTION') }, ]) as SelectOption[]; const render

  • react性能优化useMemo与useCallback使用对比详解

    目录 引言 对比 useMemo useCallback 引言 在介绍一下这两个hooks的作用之前,我们先来回顾一下react中的性能优化.在hooks诞生之前,如果组件包含内部state,我们都是基于class的形式来创建组件.当时我们也知道,react中,性能的优化点在于: 调用setState,就会触发组件的重新渲染,无论前后的state是否不同 父组件更新,子组件也会自动的更新 基于上面的两点,我们通常的解决方案是:使用immutable进行比较,在不相等的时候调用setState:在

  • React useMemo和useCallback的使用场景

    useMemo 我们知道当父组件发生重新渲染时,其所有(状态.局部变量等)都是新的.一旦子组件依赖于父组件的某一个对象变量,那么无论对象是否发生变化,子组件拿到的都是新的对象,从而使子组件对应的 diff 失效,依旧会重新执行该部分逻辑.在下面的例子中,我们的副作用依赖项中包含了父组件传入的对象参数,每次父组件发生更新时,都会触发数据请求. function Info({ style, }) { console.log('Info 发生渲染'); useEffect(() => { consol

  • 详解使用React.memo()来优化函数组件的性能

    React核心开发团队一直都努力地让React变得更快.在React中可以用来优化组件性能的方法大概有以下几种: 组件懒加载(React.lazy(...)和<Suspense />) Pure Component shouldComponentUpdate(...){...}生命周期函数 本文还会介绍React16.6加入的另外一个专门用来优化函数组件(Functional Component)性能的方法: React.memo. 无用的渲染 组件是构成React视图的一个基本单元.有些组件

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

    目录 问题背景 useMemo 进行优化 React.memo 进行优化 props的值是基本类型 props的值是引用类型 写在最后 问题背景 大家在使用 React 框架进行开发时一定遇到过以下问题: 当函数式组件中的某一状态改变,整个组件刷新,重新渲染 在类组件中 setState() 时,整个组件也会重新渲染 以上问题若不进行优化,导致的结果是: 随着代码的增加,每次的状态改变,页面进行一次 reRender ,这将产生很多不必要的 reRender 不仅浪费性能,从而导致页面卡顿: u

  • React.memo函数中的参数示例详解

    目录 React.memo?这是个啥? React.memo的第一个参数 父组件 子组件 React.memo优化 React.memo的第二个参数 父组件 子组件 React.memo优化 父组件 子组件 小结 React.memo?这是个啥? 按照官方文档的解释: 如果你的函数组件在给定相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在 React.memo 中调用,以此通过记忆组件渲染结果的方式来提高组件的性能表现.这意味着在这种情况下,React 将跳过渲染组件的操作并直

  • 六分钟带你快速学会react中的useMemo

    目录 概念 useMemo 栗子 筛选偶数 每秒获取时间刷新页面 如何优化 useCallback.React.memo 总结 概念 react 中是通过一次次的 re-render (重新渲染)保持我们的值及时的更新到页面上的,每次重新渲染都是一次快照,可以把它想象成一张张的照片,在某个时刻它应该是什么样子的 useMemo 把创建函数和依赖数组项作为参数传入 useMemo,它仅仅会在数组依赖项中的值改变时才会重新计算值 这种优化有助于避免在每次渲染时都进行高开销的计算 useMemo 的函

  • 使用react的7个避坑案例小结

    React是个很受欢迎的前端框架.今天我们探索下React开发者应该注意的七个点. 1. 组件臃肿 React开发者没有创建必要的足够多的组件化,其实这个问题不局限于React开发者,很多Vue开发者也是. 当然,我们现在讨论的是React 在React中,我们可以创建一个很多内容的组件,来执行我们的各种任务,但是最好是保证组件精简 -- 一个组件关联一个函数.这样不仅节约你的时间,而且能帮你很好地定位问题. 比如下面的TodoList组件: // ./components/TodoList.j

  • 记一个React.memo引起的bug

    目录 一般memo用法: 问题描述 解决方法 方案一.使用useRef+forceUpdate方案 方案2.使用useCallback 总结 与PureComponent不同的是PureComponent只是进行浅对比props来决定是否跳过更新数据这个步骤,memo可以自己决定是否更新,但它是一个函数组件而非一个类,但请不要依赖它来“阻止”渲染,因为这会产生 bug. 一般memo用法: import React from "react"; function MyComponent(

  • React memo减少重复渲染详解

    目录 1. 概述 2. 使用 1. 概述 此方法是一个 React 顶层 Api 方法,给函数组件来减少重复渲染,类似于 PureComponent 和 shouldComponentUpdate 方法的集合体. React.memo顶层Api方法,它可以用来减少子组件的重复渲染次数,从而提升组件渲染性能. React.memo它是一个只能在函数组件中使用的顶层Api方法. 当父组件发生改变时,默认情况下它的子孙组件也会重新渲染,当某些子组件不需要更新时,也会被强制更新,为了避免这种情况,我们可

  • 浅谈react受控组件与非受控组件(小结)

    我们都知道,有许多的web组件可以被用户的交互发生改变,比如:<input>,<select>,或者是我现在正在使用的富文本编辑器.这些组件在日常的开发中很不显眼,我们可以很轻易的通过输入一些内容或者设置元素的value属性来改变组件的值.但是,因为React是单向数据流绑定的,这些组件可能会变得失控: 1.一个维护它自己state里的value值的<Input>组件无法从外部被修改: 2.一个通过props来设置value值的<Input>组件只能通过外部

随机推荐