React useCallback 函数使用说明

2023-05-16

React 中useCallback的作用:函数相等性检查

useCallback 的函数原型:

useCallback(callbackFun, deps)

如果deps给出的依赖值不变 ,则useCallback在两次渲染阶段之间返回相同的函数实例。

考察如下代码:

function func_factory() {
  return (a, b) => a + b;
}

const sum1 = func_factory();
const sum2 = func_factory();

sum1(1, 2); // => 3
sum2(1, 2); // => 3

sum1 === sum2; // => false
sum1 === sum1; // => true

sum1 和 sum2 是将两个数字相加的函数,它们是由 func_factory() 函数创建的。

函数 sum1 和 sum2 共享相同的代码源,但是它们是不同的对象,比较它们 sum1 === sum2 结果为 false。这就是JavaScript的工作方式,对象(包括函数对象)仅等于其自身。

在React中, 共享相同代码的不同函数实例往往在React组件内部创建。

当 React 组件主体创建一个函数(例如回调或事件处理程序)时,这个函数会在每次渲染时重新创建。

例如如下代码

handleClick 在 MyComponent 的每次渲染中都是一个不同的函数对象。

import React from 'react';

function MyComponent() {
  // handleClick在每次渲染时重新创建
  const handleClick = () => {
    console.log('Clicked!');
  };

  // ...
}

因为内联函数很“便宜”,所以React在每次渲染时重新创建函数不是问题,React的每个组件有几个内联函数是可以接受的。

然而,在某些情况下,你需要保留一个函数的一个实例,在React中以下情况需要保持内联函数的的变量值不变:

1)包装在 React.memo()(或 shouldComponentUpdate )中的组件接受回调prop。
2)当函数用作其他hooks的依赖项时 useEffect(...,[callback])

useCallback 函数可以保证在deps不变的情况下,相同的代码片段返回同一个函数对象。

例如如下代码:

import React, { useCallback } from 'react';

function MyComponent() {
  // handleClick是同一个函数对象
  const handleClick = useCallback(() => {
    console.log('Clicked!');
  }, []);

  // ...
}

handleClick 变量将在 MyComponent 不同的渲染周期之间始终保持返回相同的回调函数对象实例。

一个用于理解useCallback的示例:

如下代码,需要渲染一个大的列表,

import React from 'react';

function MyBigList({ items, handleClick }) {
  const map = (item, index) => (
    <div onClick={() => handleClick(index)}>{item}</div>;
  );
  return <div>{items.map(map)}</div>;
}

export const MyBigList = React.memo(MyBigList);

MyBigList 渲染了一个项目列表,这个列表可能很大,可能有几百个元素。要保留重新渲染的列表,可以将其封装到 React.memo 中。

MyBigList 的父组件需要提供元素列表和点击事件处理回调函数。

调用MyBigList的父组件及其示例代码如下:

import React from 'react';

import useSearch from './fetch-items';

function MyParent({ term }) {
  const handleClick = useCallback((item) => {
    console.log('You clicked ', item);
  }, [term]);

  const items = useSearch(term);

  return (
    <MyBigList
      items={items}
      handleClick={handleClick}
    />
  );
}

handleClick 回调函数由 useCallback() 记忆。只要 term 变量保持不变,useCallback() 就会返回相同的函数对象实例。

现在由于某些原因重新启用了 MyParent 组件,handleClick 仍保持不变,并且不会破坏 MyBigList的记忆,列表将避免重新渲染,提高性能。

一个错误使用useCallback的示例:

import React, { useCallback } from 'react';

function MyComponent() {
  const handleClick = useCallback(() => {
    // handle the click event
  }, []);

  return <MyChild onClick={handleClick} />;
}

function MyChild ({ onClick }) {
  return <button onClick={onClick}>I am a child</button>;
}

以上示例代码用useCallback记住 handleClick 是否有意义?

答案时:没有意义,因为调用 useCallback() 其实需要很多工作,每次渲染 MyComponent 时,都会调用 useCallback() Hook。

从内部来讲,React确保返回相同的对象函数实例。即便如此,内联函数仍然在每次渲染时重新创建,useCallback 只是跳过了它,返回内部记录的原始实例而已。

即使用 useCallback() 返回相同的函数实例,也不会带来任何好处,因为优化要比没有优化花费更多。

不要忘记增加的代码复杂性,你必须确保 useCallback() 的 deps 与您在 memoized 回调中使用的 deps 保持同步。

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

React useCallback 函数使用说明 的相关文章

  • RISC和CISC的区别

    文章目录 复杂指令集计算机 CISC 精简指令集计算机 RISC CISC与RISC的区别参考文章 RISC 精简指令集计算机 和CISC 复杂指令集计算机 是当前CPU的两种架构 它们的区别在于不同的CPU设计理念和方法 复杂指令集计算机
  • 单链表逆序(C语言)

    最近在复习数据结构 xff0c 刷题正好遇上 xff0c 所以整理一下 span class token macro property span class token directive keyword include span span
  • 各种颜色RGB值

    各种颜色RGB值 RGB 255 192 203 pink xff08 粉红 xff09 RGB 220 20 60 crimson xff08 腥红 xff09 RGB 255 240 245 lavenderblush xff08 苍白
  • 第一范式、第二范式、第三范式、BCNF范式详解

    文章目录 0 范式 NF 1 第一范式 xff08 1NF xff09 2 第二范式 xff08 2NF xff09 2 1 函数依赖2 1 1完全函数依赖2 1 2 部分函数依赖2 1 3 传递函数依赖 2 2 码2 3 非主属性 3 第
  • 数据库实体关系图(ERD)及其画法

    文章目录 1 什么是ER图 2 什么时候画ER图 2 1 数据库设计2 2 数据库调试2 3 数据库创建和补丁2 4 帮助收集需求 3 ERD符号指南4 概念 逻辑和物理数据模型5 如何绘制ER图 数据库绝对是软件系统不可分割的一部分 在数
  • Threads(异步和多线程)

    Task是 NET Framework3 0出现的 xff0c 线程是基于线程池的 xff0c 然后提供丰富的api xff0c Thread方法很多很强大 xff0c 但是太过强大 xff0c 没有限制 DoSomethingLong方法
  • Linux系统中添加库文件路径的方法

    文章目录 方法一方法二 库文件在链接 xff08 静态库和共享库 xff09 和运行 xff08 仅限于使用共享库的程序 xff09 时被使用 xff0c 其搜索路径是在系统中进行设置的 一般 Linux 系统把 lib和 usr lib
  • Linux 环境下 Qt 可执行程序依赖库打包脚本

    文章目录 一 利用 96 ldd 96 命令查看程序需要的依赖库二 编写依赖库打包脚本三 编写执行文件脚本四 总结 Linux 环境下 Qt 可执行程序依赖库打包脚本 使用 Qt Creator 完成程序编码之后 xff0c 虽然会在 De
  • RSA/ECDSA host key has changed 错误

    RSA host key for mysharebook cn has changed and you have requested strict checking Host key verification failed 这是Linux重
  • VS2013+Python在图像处理中的应用

    对Python的学习要从视频编码说起 其实 xff0c 我一直在用ffmpeg对视频做设计 处理 xff0c 后来发现Opencv也能干同样的事情 xff0c 就想研究一下Opencv是怎么实现的 xff0c 再后来就和Python扯上关系
  • 结构化数据、半结构化数据和非结构化数据

    本文转自http blog csdn net u010069220 article details 46895169 在实际应用中 xff0c 我们会遇到各式各样的数据库如nosql非关系数据库 xff08 memcached xff0c
  • linux中与文件系统相关的命令

    文章目录 前言一 软链接与硬链接二 磁盘与目录容量2 1 df2 1 1 功能2 1 2 范例 2 2 du2 2 1 功能2 2 2 范例 三 磁盘分区 格式化与挂载3 1 分区3 2 格式化3 3 挂载 四 文件及目录的相关操作4 1
  • 解析Windows 2000/XP进程工作集

    在 解析Windows 2000 XP物理内存管理 中我详细的介绍了页框数据库 Page Frame Database 的概念 xff0c 提到在物理内存的组织与管理方面对于每个页面系统都在页框数据库中保存一个结构 xff0c 用于跟踪页面
  • 洛谷 P1025 数的划分

    重点内容 设F i j 为用j个数组成i xff0c 答案为F 7 3 的话 一个思路是 xff0c 对于F 7 3 61 不含1的方案数 43 含1的方案数 F i j 61 a i j 43 b i j 子问题 a i j 61 F i
  • ubuntu出现有线已连接却无法上网的解决方法(ubuntu连不上网)

    ubuntu出现有线已连接却无法上网 xff0c 执行下面的命令可以解决 复制代码 代码如下 sudo sysctl net ipv4 conf default rp filter 61 0 sudo sysctl net ipv4 con
  • codeforces1165D. Almost All Divisors

    题目链接 琪亚娜世界第一可爱 给出n个因数 xff0c 求最小的数num xff0c 使得除1和num以外的因数都在给出的这n个数中 xff0c 如果不存在输出 1 很水的一道题 xff0c 但比赛的时候总在想怎么用lcm做 xff0c 然
  • 写出一个算法函数,判定所给的操作序列是否合法。若合法,返回true,否则返回false

    源代码 xff0c 可以运行 span class token macro property span class token directive keyword include span span class token string l
  • 【硬件】玩客云 armbian 死机问题解决办法

    分析 网上看过大部分的案例在恩山论坛比较常见 xff0c 主要原因是EMMC模块存在硬件瑕疵 xff0c 因此容易在CPU满载时 xff0c 温度过高导致死机 xff0c 主流的解决方案是降频 恩山论坛 玩客云案例 解决过程 可以用来进行检
  • 昨天突然想远程登陆vnc,控制树莓派,结果忘记密码了!!!

    树莓派vncserver xff1a 输入vncserver或者tightvncserver xff0c 会启动vnc远程控制可行 xff0c 同时会显示登陆号 例如1 xff1a New 39 X 39 desktop israspber
  • Win10下VS2015(WDK10)驱动开发环境配置

    1 概述 微软在 WDK7600 以后就不再提供独立的内核驱动开发包了 xff0c 而是必须首先安装微软集成开发环境VisualStudio xff0c 然后再从微软官网下载集成的WDK开发包 或者离线安装包 xff0c 但是安装后Visu

随机推荐