React Hook的用法: memo + useCallback (四)

2023-11-01 04:10

本文主要是介绍React Hook的用法: memo + useCallback (四),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

React Hook的用法

React.memo

作用

React.memo的作用主要是用于缓存组件,使得组件可以按照业务的需求决定是否来更新的效果,比如业务场景中常见的一个场景,在页面的底部有一个版权说明,一般这是各个模块页面所公用的一个组件,但这个组件基本就是一个静态的文案描述,如果父组件数据变化更新的时候这个抽象出来的版权组件也无需更新,这样可以达到减少页面性能开销的目的。

在线示例

下面设计了一组三个不同效果的Demo做对比,父组件中有两个变量 age 和account传递给子组件,并且在父组件中可以更新这两个值。比较达到的效果如下表所列:

  1. Demo1 正常使用,父组件更新age 和account->父组件更新->子组件更新
  2. Demo2 使用 React.memo 来缓存子组件,父组件更新age 和 account->子组件不会更新
  3. Demo3 使用React.memo的第二个参数来达到选择行的更新,age变化时候子组件更新,account更新时不更新

展示效果如下所示:
在这里插入图片描述
在线Demo

在例子中的没个子组件中都打印出了一些信息,每当子组件重复渲染的时候都会打印出日志。

关键代码

import { useState, memo } from "react";

从React 中结构赋值的方式引入memo,当然也可以直接使用React.memo的写法

const MemoChild = memo(() => {console.log("子组件函数MemoChild...");return (<div className="child-container">这是子组件,内容固定,父组件更新的时候,我可以不用更新</div>);
});

可以看到memo是一个高阶组件,接受一个业务组件即可达到demo2的效果。一般如果子组件是一个纯展示的傻瓜组件,这么写就可以,如果子组件也是有逻辑需要根据父组件的变化来 ”选择性“的更新的时候,这个时候就需要使用第二个参数了。关键代码如下:

const MemoChild = memo(() => {console.log("子组件函数MemoChild...");return (<div className="child-container">这是子组件,内容固定,父组件更新的时候,我可以不用更新</div>);},(pre, next) => {console.log(pre, next);return pre.age === next.age;}
);

可以看到,memo的第二个参数也是一个函数,该函数接受两个参数,分别是之前的属性状态值和下一个属性的状态值,那就可以在这里做一些业务的判断来决定子组件是否需要更新,返回true标识前后两个状态值一样,则不更新,返回false则表示前后两个状态的值不一样则会更新,从而达到 子组件”选择性“的去更新的效果类似Demo3
如果不传的第二个参数的话,默认前后两个状态会做浅比较,根据这个比较的结果来决定子组件是否更新。

useCallback

作用

一言以蔽之其作用就是来缓存某个函数,就好像 useMemo是缓存某个变量一样,useCallback 是用来缓存某个函数。避免一个函数的更新导致某个组件随着一起更新。
可能这样比较晦涩,直接看一个Demo,就可以理解了。

在线示例

例子的目的是希望父组件中能同步展示子组件输入框中输入的值。
那一般我们会这么写,父组件会传递给子组件一个onChange函数,自子组件会在Input输入框中监听onChang事件,并在每次输入框发生变化的时候去触发父组件传递过来的onChange事件。这样做没有问题,可以达到我们预期的功能,但你会发现每次输入框变化的时候,子组件都会重新更新一遍,但其实在这个场景中,子组件是不需要重新渲染的。只希望父组件能监听到子组件的onChange事件并获取输入的值展示即可。效果如下:
在这里插入图片描述
可以看到效果是达到预期的,但是随着输入框的变化,子组件一直在重复渲染。
原因如下:
用户输入->触发子组件onChange事件->触发父组件handleChange函数->父组件修改inputTxt的状态值->状态值改变导致父组件重新渲染->handleChange函数体会重新注册一遍->传递给子组件的onChange也会一起变(这个时候的onChange事件和之前的并不一样)->子组件重复渲染
因为上面的这个逻辑所以才导致了这个现象,所以就出现了useCallback的Hook,来规避这种重复渲染浪费性能的现象。先看使用之后达到的效果如何:

在这里插入图片描述
可以看到实现的效果和上面是一样的,但这里使用了useCallback之后就很好的规避了子组件重复渲染的问题。

在线Demo

关键代码

const handleChange = useCallback(e => {setInputTxt(e.target.value);}, []);

在父组件定义 handleChange 的时候使用 useCallback包裹一下,同样的这里的第二个参数也是依赖项。可以看到用法和 uesMemo, useEffect几乎一样。只是作用的对象有所不一样而已。
当然子组件也还是需要使用React.memo包裹一下,否则不work

const Child = memo(props => {console.log("子组件渲染Demo2...");return (<div className="child-container mt10"><Input placeholder="input" onChange={props.onChange} /></div>);
});

总结

这里将 memo, useMemo, useCallback 三个Hook放在一起做个对比归纳如下:

  1. React.memo 缓存组件,使得组件可以 ”有选择“的更新
  2. useMemo 缓存某个变量,第二个参数是依赖项。使得函数组件变量变化时候,组件可以”有选择“的去执行某些业务
  3. useCallBack 缓存某个方法,特别是子组件调父组件的场景,避免子组件重复渲染,useCallBack其实是 useMemo的一种简单用法,也可以直接使用useMemo 来缓存方法,不过一般使用useCallBack的比较多

这篇关于React Hook的用法: memo + useCallback (四)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/320380

相关文章

C#中async await异步关键字用法和异步的底层原理全解析

《C#中asyncawait异步关键字用法和异步的底层原理全解析》:本文主要介绍C#中asyncawait异步关键字用法和异步的底层原理全解析,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结C#异步编程

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

前端CSS Grid 布局示例详解

《前端CSSGrid布局示例详解》CSSGrid是一种二维布局系统,可以同时控制行和列,相比Flex(一维布局),更适合用在整体页面布局或复杂模块结构中,:本文主要介绍前端CSSGri... 目录css Grid 布局详解(通俗易懂版)一、概述二、基础概念三、创建 Grid 容器四、定义网格行和列五、设置行

python3 gunicorn配置文件的用法解读

《python3gunicorn配置文件的用法解读》:本文主要介绍python3gunicorn配置文件的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录python3 gunicorn配置文件配置文件服务启动、重启、关闭启动重启关闭总结python3 gun

MySQL 中的 LIMIT 语句及基本用法

《MySQL中的LIMIT语句及基本用法》LIMIT语句用于限制查询返回的行数,常用于分页查询或取部分数据,提高查询效率,:本文主要介绍MySQL中的LIMIT语句,需要的朋友可以参考下... 目录mysql 中的 LIMIT 语句1. LIMIT 语法2. LIMIT 基本用法(1) 获取前 N 行数据(

C#中DrawCurve的用法小结

《C#中DrawCurve的用法小结》本文主要介绍了C#中DrawCurve的用法小结,通常用于绘制一条平滑的曲线通过一系列给定的点,具有一定的参考价值,感兴趣的可以了解一下... 目录1. 如何使用 DrawCurve 方法(不带弯曲程度)2. 如何使用 DrawCurve 方法(带弯曲程度)3.使用Dr

前端下载文件时如何后端返回的文件流一些常见方法

《前端下载文件时如何后端返回的文件流一些常见方法》:本文主要介绍前端下载文件时如何后端返回的文件流一些常见方法,包括使用Blob和URL.createObjectURL创建下载链接,以及处理带有C... 目录1. 使用 Blob 和 URL.createObjectURL 创建下载链接例子:使用 Blob

Vuex Actions多参数传递的解决方案

《VuexActions多参数传递的解决方案》在Vuex中,actions的设计默认只支持单个参数传递,这有时会限制我们的使用场景,下面我将详细介绍几种处理多参数传递的解决方案,从基础到高级,... 目录一、对象封装法(推荐)二、参数解构法三、柯里化函数法四、Payload 工厂函数五、TypeScript

C++ vector的常见用法超详细讲解

《C++vector的常见用法超详细讲解》:本文主要介绍C++vector的常见用法,包括C++中vector容器的定义、初始化方法、访问元素、常用函数及其时间复杂度,通过代码介绍的非常详细,... 目录1、vector的定义2、vector常用初始化方法1、使编程用花括号直接赋值2、使用圆括号赋值3、ve

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分