React解密:React Hooks函数之useCallback和useMemo

2023-11-19

之所以将useCallback和useMemo放到一起,从某种意义上说,他们都是性能优化的始作俑者,他们也有很多的共性。我们先来回顾一下class组件性能优化的点:

  1. 调用 setState,就会触发组件的重新渲染,无论前后 state 是否相同
  2. 父组件更新,子组件也会自动更新

介于这俩点,我们一般使用 immutable 进行比较,在不相等的时候调用 setState, 在 shouldComponentUpdate 中判断前后的 props 和 state,如果没有变化,则返回 false 来阻止更新。

但是当hooks到来后,没有了shouldComponentUpdate函数。无法判断前后的props是否相同,从而是不是要从新渲染,useEffect函数并没有区分是mount还是update,这样一来,也就意味着,每次组件的更新都会执行其复杂的逻辑,性能的消耗将是非常大的。

所以,在hooks时代,就诞生了useCallback和useMemo这样的性能优化函数,其实,useCallback和useMemo和useEffect的参数一致,但是,useEffect可以处理副作用,而后俩者不可以。useCallback 和 useMemo 都会在组件第一次渲染的时候执行,之后会在其依赖的变量发生改变时再次执行;并且这两个hooks都返回缓存的值,useMemo 返回缓存的 变量,useCallback 返回缓存的 函数。

React.memo()

还记得在class组件时代我们如何做优化吗?对,没错,俩中方法:

(1)pureComponent,对props进行浅比对

(2)shouldComponentUpdate根据返回值来处理是否要更新

在function时代,已经没有了pureComponent和shouldComponentUpdate这种东西,而是react提供了React.memo这样的高阶组件,与pureComponent和相似,但是,这个高阶组件并不是适用于class组件,而只为function组件服务。相比于 PureComponent ,React.memo() 可以支持指定一个参数,可以相当于 shouldComponentUpdate 的作用,因此 React.memo() 相对于 PureComponent 来说,用法更加方便。

用法:

function MyComponent () {}

function areEqual(prevProps, nextProps) {
  /*
  return true if passing nextProps to render would return
  the same result as passing prevProps to render,
  otherwise return false
  */
}
export default React.memo(MyComponent, areEqual);

看上面的代码,其实,用法很简单。在 Function Component 之外,在声明一个 areEqual 方法来判断两次 props 有什么不同,如果第二个参数不传递,则默认只会进行 props 的浅比较。最终 export 的组件,就是 React.memo() 包装之后的组件。在某些情况下,React.memo的第二个参数是必须的。

总的来说,React.memo()方法,是让整个组件要不要re-render,记住这一点很重要,但是,有的时候,我们想要组件的某一部分要不要re-render,而不是整个组件要不要re-render.怎么办?yes,就是useMemo();

useMemo() 细粒度性能优化

用法:

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

useMemo() 返回的是一个 memoized 值,只有当依赖项(比如上面的 a,b 发生变化的时候,才会重新计算这个 memoized 值)

memoized 值不变的情况下,不会重新触发渲染逻辑。说到渲染逻辑,需要记住的是 useMemo() 是在 render 期间执行的,所以不能进行一些额外的副操作,比如网络请求等。如果没有提供依赖数组(上面的 [a,b])则每次都会重新计算 memoized 值,也就会 re-redner。

useCallback函数

const fnA = useCallback(fnB, [a])

useCallback的用法其实和useMemo是一样的,但是他们唯一的区别是,useCallback是缓存了函数。

场景:在开发中,你会遇到这样的场景,需要从父组件中传递一个函数到子组件,如果我们不用useCallback包裹,那么也就意味着,只要父组件有更新,都会向子组件去传递一个新函数,虽然说每次传递的函数都一样,但是依旧是俩个不同的对象。但是如果使用了useCallback, useCallback 就会根据依赖项是否发生变化,从而决定是否返回一个新的函数,函数内部作用域也随之更新。

总的来说:

  1. 在子组件不需要父组件的值和函数的情况下,只需要使用 memo 函数包裹子组件即可。

  2. 如果有函数传递给子组件,使用 useCallback

  3. 如果有值传递给子组件,使用 useMemo

  4. useEffectuseMemouseCallback 都是自带闭包的。也就是说,每一次组件的渲染,其都会捕获当前组件函数上下文中的状态(state, props),所以每一次这三种hooks的执行,反映的也都是当前的状态,你无法使用它们来捕获上一次的状态。对于这种情况,我们应该使用 ref 来访问。

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

React解密:React Hooks函数之useCallback和useMemo 的相关文章

  • 必须返回有效的 React 元素或 null -- Reactjs 错误

    拜托 我遇到了一些对我来说很难修复的错误 我下面有一个简单的反应组件 import React from react const ForumPostComponent topics gt const forums topics return
  • 将 React 值从子级传递给父级

    我正在努力解决一些可能非常简单的事情 我的父组件是一个搜索小部件 它需要使用在单独的抽屉组件中定义的过滤器 目前 用户可以输入搜索查询 该查询会调用 API 并且需要根据抽屉组件中的选择器来过滤结果 但是 我无法将父母和孩子联系起来以实现这
  • 如何使用react-router通过路由将props传递给react组件?

    我想将一些道具传递给 IndexRoute 上的组件 下面是我的代码片段 render root Element const store params this as any ReactDOM render
  • 使用单个 shell 脚本运行 React 和 Flask

    我构建了一个使用 ReactJS 作为前端和 Flask 作为中间件的应用程序 我可以使用以下命令序列来执行它 npm start cd Equation Solver python m flask run 执行第一个命令后 我必须打开另一
  • 表单验证后 isValid 保持 false

    我有一个自定义验证函数 但即使它没有返回错误 表单仍然无效 我将以下属性传递给 Formik validate import files gt return import files values length 0 import files
  • 如何使用 React 传递自定义服务器主机名?

    我希望能够在运行 React 应用程序时传递自定义服务器主机名 以便在需要获取数据时在 URL 中使用 服务器当前正在我的本地计算机上运行 因此当我使用获取 我一直在使用 http localhost 效果非常好 但我希望能够传递要在 UR
  • 获取:使用获取响应设置变量并从函数返回[重复]

    这个问题在这里已经有答案了 我对 JavaScript 和 React 还很陌生 我有一个来自组件的回调 该组件从给定 id 的服务器获取 customer name 提取工作正常 console log 正确打印全名 但最后一个 then
  • 任务“:app:compileDebugJavaWithJavac”执行失败。运行 React Native 项目时

    我正在我真正的 Android 设备上运行现有的 React Native 项目 然后不知何故弹出这个错误 错误总是关于 找不到符号 我有 JDK 和 SDK 并将其添加到我的系统变量中 但我仍然不知道为什么它会给我这样的错误 我记得我只是
  • 将 chrome api 与 React.js 结合使用

    我一直在尝试使用 React 制作一个简单的 Chrome 扩展 清单看起来像这样 name New Tab version 1 0 manifest version 2 description A minimalist replaceme
  • 如何将 !important 添加到 CSS-in-JS (JSS) 类属性?

    我正在尝试使用一些 CSS in JS 类这个答案 https stackoverflow com questions 54525334 how can i change the label size of a material ui te
  • 如何在reactJS中显示从输入类型=文件中选择的图像

    我正在尝试在我的网络应用程序中显示从我的计算机中选择的图像 我提到了以下问题 它解决了我试图解决的问题 如何在不向服务器发送数据的情况下显示选定的图像 https stackoverflow com questions 17138244 h
  • 是的/Formik 异步验证与去抖

    如何将去抖应用于下面的异步验证 代码来自 Yup 的 github https github com jquense yup mixedtestname string message string function test functio
  • 如何通过单击按钮从反应状态挂钩数组中删除对象

    我正在尝试制作一个按钮 根据传递的索引从数组 即状态 中删除一个对象 我已经尝试了很多 但我的方法都不起作用 所以这是代码 希望我可以找人帮忙 state const items setItems useState name quantit
  • Redux 中的排队操作

    我目前遇到的情况是我需要连续运行 Redux Actions 我看过各种中间件 比如 redux promise 看起来不错如果您知道触发根操作 由于缺乏更好的术语 时的连续操作是什么 本质上 我想维护一个可以随时添加的操作队列 每个对象在
  • React 路由器重定向页面但组件未渲染

    我在路由更改时渲染组件时遇到一个奇怪的问题 我使用的版本 react 16 9 0 react dom 16 9 0 react router dom 5 1 0 这是我的路线配置 const Routes gt const isLogge
  • 提交后清除 React 中的表单

    我试图在使用 Axios 创建表单提交后清除表单数据 消息处理良好 响应记录到页面 但每个文本字段中的数据在提交后仍保留在页面上 我尝试添加一个resetForm函数 我将表单设置回原来的空白状态 但这不起作用 import React C
  • 在 React Native 的 Flatlist 中使用自定义元素的参数进行导航:空参数

    在没有成功解决我的问题之后here https stackoverflow com questions 67862370 navigation with parameters from custom element in flatlist
  • React/Typescript ForwardRef 类型用于返回输入或文本区域的元素

    我正在尝试使用 React 和 TypeScript 为我们的应用程序创建一个通用文本输入组件 我希望它能够成为基于给定 prop 的输入元素或文本区域元素 所以它看起来有点像这样 import TextArea Input from ou
  • MUI 数据表上的 selectRow

    这是我第一次尝试MUI 数据表 https github com gregnb mui datatables在反应中 我想从复选框中选择的行中获取数据 const options download false print false vie
  • 如何使用 Material UI 制作一个圆形复选框?

    我尝试匹配的设计要求复选框为圆形 我正在使用 Material UI 和 React 边框半径不起作用 因为实际图标的边框不是可见复选框的边框 我不能只使用像 Font Awesome 这样的东西 因为它需要实际检查和取消检查 Curren

随机推荐

  • Window下用caffe实现MNIST训练

    本博包含MNIST原始数据的格式转化 以及分类训练 1 数据转化 Caffe源码中src caffe caffe examples mnist convert mnist data cpp提供的实现代码并不能直接在Windows下运行 这里
  • Filebeat监控 日志监控

    介绍 filebeat提供了两种监控 一种直接推送到ES集群 第二种就是Metricbeat 这里介绍第一种 也就四部 第1步 创建认证 账号密码 这一步基本可以略过了 如果你的filebeat在运行 你肯定已经有账号密码了 第2步 配置f
  • 设计模式学习笔记-工厂模式

    设计模式学习笔记 工厂模式 作用 实现了创建者和调用者的分离 详细分类 简单工厂模式 用来生产同一等级结构中的任意产品 对于增加新的产品 必须要扩展已有的代码 工厂方法模式 用来生产同一等级结构中的固定产品 支持增加任意产品 抽象工厂模式
  • 基于Zinx框架实现轻量级TCP服务器

    一 框架部分 包括一个sever 两个读 写模块 一个API管理 一个消息队列管理 一个读写池 建目录一个抽样层 一个实体层 二 基于zinx服务器的应用 对于一个框架 越简单来说越好 V0 1 简单的服务器客户端 1 对于开始 完成简单的
  • 使用CMake构建复杂工程

    转 https www cnblogs com autophyte p 6147751 html 0 什么是CMake CMake是一个跨平台的编译 安装 测试以及打包工具 CMake不直接编译软件 而是结合原生构建系统来构建软件 CMak
  • 计算机视觉之目标检测——R-CNN、Fast R-CNN和Faster R-CNN详解

    计算机视觉之目标检测 R CNN Fast R CNN和Faster R CNN详解 文章目录 计算机视觉之目标检测 R CNN Fast R CNN和Faster R CNN详解 目标检测的任务 目标检测的方法 R CNN Fast R
  • yagmail发送邮件

    分五步实现 1 导入yagmail第三方库 2 连接邮箱 3 添加邮件内容 4 发送邮件 5 释放邮箱 导入yagmail第三方库 import yagmail yagmail SMTP user 邮箱名 host SMTP服务器域名 ya
  • Vue 下拉框值变动事件传多个参数

    在使用 Vue 进行开发时 下拉框值变动事件 change 是很常用的 其传参一般分为两种方式 默认传参和自定义传参 默认传参 change 默认会传选中项标识的参数 在传参处不用定义 在方法中直接接受即可
  • Linux下的ssh

    SSH 为 Secure Shell 的缩写 由 IETF 的网络工作小组 Network Working Group 所制定 SSH 为建立在应用层和传输层基础上的安全协议 SSH 是目前较可靠 专为远程登录会话和其他网络服务提供安全性的
  • 将MindManager添加到鼠标右键新建项

    事情缘起于自己做事习惯为每个项目添加一个思维导图作为项目总看板 但每次都需要自己通过软件新建一个空白文件 再将空白文件索引到项目文件夹 再更名保存 虽然步骤不太多 但每次都需要这样的操作确实让我很困扰 所以就心想能不能让Mindmanage
  • ORM 的功能

    ORM要完成对象的初始化以及CRUD功能 在这些功能中尤其是query和update已经蕴含了相应的map的功能 除此之外还要提供transaction和concurrency的功能 这些基本的功能很好理解 不过相应的实现是比较复杂的 还要
  • 机器学习之朴素贝叶斯

    机器学习之朴素贝叶斯 1 朴素贝叶斯 2 朴素贝叶斯应用 3 代码实现贝努力朴素贝叶斯 4 代码实现高斯朴素贝叶斯 5 代码实现多项式朴素贝叶斯 6 总结 前言 主要介绍朴素贝叶斯的概念 公式 以及代码实现贝努利 高斯 多项式朴素贝叶斯 1
  • PyQt6 Designer与实际运行不一致问题

    我们在Designer设计布局时 会先定义好布局然后只在某个布局内存放元素 其他布局为空 可能就会产生布局不一致问题 其实已经存在了对应的布局只是里面为空 所以剩余空间优先被有元素的布局使用 我们在每个布局中加入某个组件即可解决
  • VC++ CMemDC类的扩展(新版)

    上一版本链接 https blog csdn net u012156872 article details 103755254 测试过程中发现存在问题 于是进行了功能补充 源码实现 CSWMemDC h pragma once namesp
  • vant + moment插件自定义count-down倒计时

    根据vant官网https vant ui github io vant v2 zh CN按需引入找到倒计时 自定义时间格式参考下图
  • matlab2016b版本安装

    安装包下载地址 链接 https pan baidu com s 1RrUp8TBIa7g7mhfSUtqAsg 提取码 foc1 1 解压文件包 2 在 matlab R2016b 64bit 文件下 找到 setup 文件 右击选择 以
  • 【C++】_5.模板

    目录 1 泛型编程 2 函数模板 2 1 概念 2 2 函数模板格式 2 3 函数模板原理 2 4 函数模板的实例化 2 5 函数模板的匹配原则 3 类模板 4 非类型模板参数 5 模板的特化 5 1 概念 5 2 函数模板特化 5 3 类
  • 解析request.getParameter() 和request.getAttribute() 区别

    一 request getParameter 和request getAttribute 区别 1 request getParameter 取得是通过容器的实现来取得通过类似post get等方式传入的数据 request setAttr
  • django高并发部署

    django高并发部署
  • React解密:React Hooks函数之useCallback和useMemo

    之所以将useCallback和useMemo放到一起 从某种意义上说 他们都是性能优化的始作俑者 他们也有很多的共性 我们先来回顾一下class组件性能优化的点 调用 setState 就会触发组件的重新渲染 无论前后 state 是否相