React中函数式Hooks之memo、useCallback的使用以及useMemo、useCallback的区别

简介: React中的`memo`是高阶组件,类似于类组件的`PureComponent`,用于避免不必要的渲染。`useCallback` Hook 用于缓存函数,避免在每次渲染时都创建新的函数实例。`memo`可以接收一个比较函数作为第二个参数,以确定是否需要重新渲染组件。`useMemo`用于缓存计算结果,避免重复计算。两者都可以用来优化性能,但适用场景不同:`memo`用于组件,`useMemo`和`useCallback`用于值和函数的缓存。

昨天学习了useMemo的使用,我们知道useMemo起到了缓存变量的作用。
而useCallback的作用起到了缓存函数的作用。下面我们来看一下怎么使用以及注意事项。

memo

首先我们先来学习一下memo这个函数,这个函数是从react中直接使用的这个函数是一个包裹函数;

import React, {
     memo } from 'react'

它的作用类似class组件中的pureComponent;以及shouldComponentUpdate这个钩子函数的作用。

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

用法:

const A = memo(function A(props) {
   
  let {
    giveSonFun } = props
  console.log(giveSonFun, 'giveSonFun')
  return (
    <>
      我是A组件内容
    </>
  )
})
export default A;

这样一来我们的组件就会自动的根据变量是否变化而从新渲染函数式组件;

当我们将A组件作为子组件的时候,无论父组件谁的状态更新了,它的所有子组件都会自动的进行重新渲染,有时候我们的子组件是完全没有必要重新渲染的,所有我们可以使用这个React.mome组件进行包裹,起到了纯组件(pureComponent)的作用。

useCallback

首先我们看下面的例子,我们用到了useState这个hook:

import './App.css';
import React, {
    useState, useMemo,  useCallback, memo } from 'react'
function App() {
   
  const [name, setName] = useState("LiuQing")
 const a =1
  // 类似vue 中的computed 计算属性  
  // 用于缓存变量
  const studyRun = React.useMemo(() => name + 'String', [name])
  const changeName = () => {
   
    setName("mynameiszjq" + Math.random())
  }
 // const giveSonFun = useCallback(() => {
   
 //   console.log("子组件执行了函数")
//  }, [a])

  const giveSonFun = () => {
   
     console.log("子组件执行了函数")
   }

  return (
    <React.Fragment>
      <p>studyRun:{
   studyRun}</p>
      <button onClick={
   changeName}>点击更改studyRun</button>
      <div style={
   {
    border: "2px solid #ccc", height: "300px", width: "500px" }}>
        我是A组件
      <A giveSonFun={
   giveSonFun} />
      </div>
    </React.Fragment>
  );
}

const A = memo(function A(props) {
   
  let {
    giveSonFun } = props
  console.log(giveSonFun, 'giveSonFun')
  return (
    <>
      我是A组件内容
        <hr />
      <button onClick={
   giveSonFun}>点击我执行父组件传入的方法</button>
    </>
  )
})


export default App;

在上面的例子中我们在APP组件中写个两个giveSonFun 方法,一个是用useCallback包裹的,一个是普通的函数,
我们先使用普通函数,看效果。
在这里插入图片描述
页面初始化的时候,打印了一个giveSonFun 函数体,说明我们子组件渲染了一次。
我们开始点击,APP组件中的按钮:
在这里插入图片描述
我们点击了几次,子组件A重新render了几次,说明每一次都传入了一个新的函数地址。

我们打开useCallback包裹的函数giveSonFun ,注释掉普通函数giveSonFun ;

import './App.css';
import React, {
    useState, useMemo,  useCallback, memo } from 'react'
function App() {
   
  const [name, setName] = useState("LiuQing")
   const a =1
  // 类似vue 中的computed 计算属性  
  // 用于缓存变量
  const studyRun = React.useMemo(() => name + 'String', [name])
  const changeName = () => {
   
    setName("mynameiszjq" + Math.random())
  }
  const giveSonFun = useCallback(() => {
   
    console.log("子组件执行了函数")
  }, [a])

  // const giveSonFun = () => {
   
  //   console.log("子组件执行了函数")
  // }

  return (
    <React.Fragment>
      <p>studyRun:{
   studyRun}</p>
      <button onClick={
   changeName}>点击更改studyRun</button>
      <div style={
   {
    border: "2px solid #ccc", height: "300px", width: "500px" }}>
        我是A组件
      <A giveSonFun={
   giveSonFun} />
      </div>
    </React.Fragment>
  );
}

const A = memo(function A(props) {
   
  let {
    giveSonFun } = props
  console.log(giveSonFun, 'giveSonFun')
  return (
    <>
      我是A组件内容
        <hr />
      <button onClick={
   giveSonFun}>点击我执行父组件传入的方法</button>
    </>
  )
})


export default App;

同样的页面初始话的时候,A组件渲染了一次:
在这里插入图片描述
但是后面我们点击APP函数中的按钮,打印台并没有重新打印函数体;
在这里插入图片描述
后面的随机数变化表示我们最少点击了一次,控制台还是没有打印函数体。
所以我们使用useCallback实现了缓存函数的效果。

我们不难发现,useCallback有两个参数:
第一个参数是一个函数体;
第二个参数是一个数组;
其实第二个参数和useEffect的效果一样;
当我们不传入第二个参数的时候,所有的状态改变都会触发useCallback重新返回一个新的缓存函数;
当我们你传入一个空数组的时候,所有状态的改变都不会触发useCallback重新返回一个新的缓存函数;
当我们传入一个数组,并且数组中有变量的时候,只有这个变量状态改变才会触发useCallback重新返回一个新的缓存函数;

我们上边的例子使用了一个变量a作为useCallback返回新缓存函数的条件,事实上我们的a一直没有变;
当我们将a换成 name后,这个缓存函数会根据name变量改变与否来返回新缓存函数与否;

import './App.css';
import React, {
    useState, useMemo,  useCallback, memo } from 'react'
function App() {
   
  const [name, setName] = useState("LiuQing")
  // 类似vue 中的computed 计算属性  
  // 用于缓存变量
  const studyRun = React.useMemo(() => name + 'String', [name])
  const changeName = () => {
   
    setName("mynameiszjq" + Math.random())
  }
  const giveSonFun = useCallback(() => {
   
    console.log("子组件执行了函数")
  }, [name])


  return (
    <React.Fragment>
      <p>studyRun:{
   studyRun}</p>
      <button onClick={
   changeName}>点击更改studyRun</button>
      <div style={
   {
    border: "2px solid #ccc", height: "300px", width: "500px" }}>
        我是A组件
      <A giveSonFun={
   giveSonFun} />
      </div>
    </React.Fragment>
  );
}

const A = memo(function A(props) {
   
  let {
    giveSonFun } = props
  console.log(giveSonFun, 'giveSonFun')
  return (
    <>
      我是A组件内容
        <hr />
      <button onClick={
   giveSonFun}>点击我执行父组件传入的方法</button>
    </>
  )
})


export default App;

在这里插入图片描述
每点击一次name的值都会被重新set,所有每次传入子组件都是一个新的giveSonFun 函数,所有A组件会从新渲染。

总结:
memo:为了像纯组件一样,根据变量前后状态来判断更新组件与否;
useMemo:缓存变量;
useCallback:缓存函数;
在这里插入图片描述
附参考地址:https://blog.csdn.net/leelxp/article/details/107822103

革命尚未完成,同志还需努力

目录
相关文章
|
25天前
|
前端开发 JavaScript
React Hooks 深入解析
React Hooks 深入解析
23 0
|
25天前
|
前端开发
React Hooks:从基础到进阶的深入理解
React Hooks:从基础到进阶的深入理解
30 0
|
28天前
|
缓存 前端开发 开发者
深入理解React Hooks,打造高效响应式UI
深入理解React Hooks,打造高效响应式UI
33 0
|
2月前
|
前端开发 JavaScript 开发者
深入理解React Hooks:提升前端开发效率的关键
【10月更文挑战第5天】深入理解React Hooks:提升前端开发效率的关键
|
1月前
|
前端开发 JavaScript 开发者
颠覆传统:React框架如何引领前端开发的革命性变革
【10月更文挑战第32天】本文以问答形式探讨了React框架的特性和应用。React是一款由Facebook推出的JavaScript库,以其虚拟DOM机制和组件化设计,成为构建高性能单页面应用的理想选择。文章介绍了如何开始一个React项目、组件化思想的体现、性能优化方法、表单处理及路由实现等内容,帮助开发者更好地理解和使用React。
77 9
|
2月前
|
前端开发
深入解析React Hooks:构建高效且可维护的前端应用
本文将带你走进React Hooks的世界,探索这一革新特性如何改变我们构建React组件的方式。通过分析Hooks的核心概念、使用方法和最佳实践,文章旨在帮助你充分利用Hooks来提高开发效率,编写更简洁、更可维护的前端代码。我们将通过实际代码示例,深入了解useState、useEffect等常用Hooks的内部工作原理,并探讨如何自定义Hooks以复用逻辑。
|
2月前
|
前端开发 JavaScript API
探索React Hooks:前端开发的革命性工具
【10月更文挑战第5天】探索React Hooks:前端开发的革命性工具
|
25天前
|
监控 前端开发 数据可视化
3D架构图软件 iCraft Editor 正式发布 @icraft/player-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生
@icraft/player-react 是 iCraft Editor 推出的 React 组件库,旨在简化3D数字孪生场景的前端集成。它支持零配置快速接入、自定义插件、丰富的事件和方法、动画控制及实时数据接入,帮助开发者轻松实现3D场景与React项目的无缝融合。
94 8
3D架构图软件 iCraft Editor 正式发布 @icraft/player-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生
|
28天前
|
前端开发 JavaScript 开发者
使用React和Redux构建高效的前端应用
使用React和Redux构建高效的前端应用
33 1
|
2月前
|
前端开发 数据管理 编译器
引领前端未来:React 19的重大更新与实战指南🚀
React 19 即将发布,带来一系列革命性的新功能,旨在简化开发过程并显著提升性能。本文介绍了 React 19 的核心功能,如自动优化重新渲染的 React 编译器、加速初始加载的服务器组件、简化表单处理的 Actions、无缝集成的 Web 组件,以及文档元数据的直接管理。这些新功能通过自动化、优化和增强用户体验,帮助开发者构建更高效的 Web 应用程序。
189 1
引领前端未来:React 19的重大更新与实战指南🚀