react 中 useCallback Hook 作用

news2024/11/16 9:26:34

一、性能优化

1. 防止函数的重复创建

1.1 函数组件重新渲染问题

在 React 函数组件中,每次组件重新渲染时,内部的函数都会被重新创建。

import React from "react";



const ParentComponent = () => {

  // 每次ParentComponent重新渲染,handleClick函数都会重新创建

  const handleClick = () => {

    console.log("Button clicked");

  };



  return <ChildComponent onClick={handleClick} />;

};



const ChildComponent = React.memo(({ onClick }) => {

  return <button onClick={onClick}>Click me</button>;

});

1.2 useCallback 的解决方案

`useCallback`可以用来解决这个问题。它会返回一个记忆化(memoized)的函数,只有在依赖项发生变化时,才会重新创建该函数。

import React, { useCallback } from "react";



const ParentComponent = () => {

  // 只有在依赖项(这里没有依赖项,所以只会创建一次)改变时,handleClick才会重新创建

  const handleClick = useCallback(() => {

    console.log("Button clicked");

  }, []);



  return <ChildComponent onClick={handleClick} />;

};



const ChildComponent = React.memo(({ onClick }) => {

  return <button onClick={onClick}>Click me</button>;

});

2. 优化组件渲染树

2.1 复杂组件结构中的性能影响

在大型应用中,组件树可能非常复杂,存在多层嵌套的组件关系。当父组件重新渲染时,如果不进行优化,可能会引发大量子组件的不必要渲染,导致性能下降。`useCallback`通过稳定函数引用,减少了子组件重新渲染的连锁反应。

2.2 示例场景

假设存在一个多层级的表单组件,其中包含多个输入字段和相关的验证函数。当表单中的某个输入字段变化导致父组件重新渲染时,如果不使用`useCallback`,所有依赖这些验证函数的子组件都可能重新渲染。使用`useCallback`来包裹这些验证函数后,只有当验证函数的依赖项(如验证规则)发生变化时,函数引用才会改变,从而稳定了子组件的渲染行为。

二、依赖管理与副作用控制

1. 精确的依赖管理

1.1 与 useEffect 结合时的作用

例如:当一个副作用函数依赖于一个外部函数时,如果不进行处理,每次组件重新渲染可能会导致副作用函数被重新执行,因为外部函数的引用在每次渲染时可能不同。

import React, { useEffect, useState } from "react";



const ComponentWithEffect = () => {

  const [count, setCount] = useState(0);



  // 模拟一个外部函数,每次组件重新渲染都会重新创建

  const externalFunction = () => {

    return count * 2;

  };



  useEffect(() => {

    const result = externalFunction();

    console.log("Effect with result:", result);

  }, [externalFunction]);



  return (

    <div>

      Count: {count}{" "}

      <button onClick={() => setCount(count + 1)}>Increment</button>

    </div>

  );

};

在上述代码中,`externalFunction`的重新创建导致`useEffect`的依赖项不断变化,从而使副作用函数在每次组件重新渲染时都被执行。通过`useCallback`可以解决这个问题:

import React, { useEffect, useState, useCallback } from "react";



const ComponentWithEffect = () => {

  const [count, setCount] = useState(0);



  // 使用useCallback来记忆化externalFunction,只有count变化时才会重新创建

  const externalFunction = useCallback(() => {

    return count * 2;

  }, [count]);



  useEffect(() => {

    const result = externalFunction();

    console.log("Effect with result:", result);

  }, [externalFunction]);



  return (

    <div>

      Count: {count}{" "}

      <button onClick={() => setCount(count + 1)}>Increment</button>

    </div>

  );

};

现在,`externalFunction`只有在`count`(依赖项)变化时才会重新创建,`useEffect`的副作用函数也只会在`externalFunction`真正改变时被执行,实现了更精确的依赖管理。

2. 副作用的触发控制

2.1 避免不必要的副作用执行

例如:在一个数据获取的场景中,如果获取数据的函数由于不必要的重新创建而频繁触发,可能会对服务器造成不必要的负载,并浪费用户的网络资源。

2.2 代码示例

import React, { useEffect, useState, useCallback } from "react";



const DataFetchingComponent = () => {

  const [data, setData] = useState(null);



  // 数据获取函数,如果不进行优化,可能会频繁触发

  const fetchData = useCallback(() => {

    fetch("https://example.com/api/data")

      .then((response) => response.json())

      .then((jsonData) => setData(jsonData));

  }, []);



  useEffect(() => {

    fetchData();

  }, [fetchData]);



  return (

    <div>{data ? <pre>{JSON.stringify(data)}</pre> : "Loading data..."}</div>

  );

};

在这个例子中,`fetchData`函数使用`useCallback`进行优化,只有在`fetchData`的依赖项(这里没有依赖项,所以函数只会创建一次)变化时,才会重新创建该函数。这确保了数据获取操作(副作用)不会因为函数的不必要重新创建而频繁触发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2241411.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软间隔支持向量机支持向量的情况以及点的各种情况

软间隔支持向量 ​ 这一节我们要回答的问题是&#xff1f;如何判断一个点是软间隔支持向量机中的支持向量&#xff0c;在硬间隔支持向量机中&#xff0c;支持向量只需要满足一个等式&#xff1a; y i ( w T x i b ) − 1 0 y_i(w^Tx_i b) -1 0 yi​(wTxi​b)−10 ​ 在软间…

PCA 原理推导

针对高维数据的降维问题&#xff0c;PCA 的基本思路如下&#xff1a;首先将需要降维的数据的各个变量标准化&#xff08;规范化&#xff09;为均值为 0&#xff0c;方差为 1 的数据集&#xff0c;然后对标准化后的数据进行正交变换&#xff0c;将原来的数据转换为若干个线性无关…

在Ubuntu 24.04 LTS上安装飞桨PaddleX

前面我们介绍了《在Windows用远程桌面访问Ubuntu 24.04.1 LTS》本文接着介绍安装飞桨PaddleX。 PaddleX 3.0 是基于飞桨框架构建的一站式全流程开发工具&#xff0c;它集成了众多开箱即用的预训练模型&#xff0c;可以实现模型从训练到推理的全流程开发&#xff0c;支持国内外多…

Web_前端_HTML入门学习的案例案例1

HTML入门学习的案例 来源: HTML入门学习的案例_给学生讲html内容案例-CSDN博客 案例1&#xff1a;hello.html <html><body><title>html技术</title></body><body>hello</body> </html>&#xff08;但是有乱码&#xff09; …

【C#】C#编程入门指南:构建你的.NET开发基础

文章目录 前言&#xff1a;1. C# 开发环境 VS的基本熟悉2. 解决方案与项目的关系3. 编辑、编译、链接、运行4. 托管代码和CLR4.1 CLR&#xff1a;4.2 C# 代码第编译过程&#xff08;两次编译的&#xff09; 5. 命名空间6. 类的组成与分析7. C# 的数据类型7.1 值类型7.2 引用类型…

115页PDF | 埃森哲_XX集团信息化能力成熟度评估及能力提升方案(限免下载)

一、前言 这份报告是埃森哲_XX集团信息化能力成熟度评估及能力提升方案&#xff0c;报告首先分析了集团的战略规划&#xff0c;包括调整优化期、转型升级期和跨越发展期的目标&#xff0c;然后识别了集团面临的内部挑战和外部压力&#xff0c;如管控体系不完善、业务板块多样化…

面试时问到软件开发原则,我emo了

今天去一个小公司面试&#xff0c;面试官是公司的软件总监&#xff0c;眼镜老花到看笔记本电脑困难&#xff0c;用win7的IE打开leetcode网页半天打不开&#xff0c;公司的wifi连接不上&#xff0c;用自己手机热点&#xff0c;却在笔记本电脑上找不到。还是我用自己的手机做热点…

Wi-Fi背后的工作原理与技术发展历程介绍【无线通信小百科】

1个视频说清楚WIFI&#xff1a;频段/历程/技术参数/常用模块 智能手机拥有率越来越高的今天&#xff0c;大家已经习惯了通过无线网络上网的方式。除了在外面需要用手机流量&#xff0c;我们通常在家里或者机场&#xff0c;商场都可以通过Wi-Fi连接上网。本期文章将为大家介绍Wi…

【MySQL 保姆级教学】详细讲解视图--(15)

视图 1. 为什么要有视图&#xff1f;2.视图的定义和特点3. 创建视图4. 视图的使用举例4.1 创建表并插入数据4.2 举例 5. 视图和基表之间有什么联系呢&#xff1f; 1. 为什么要有视图&#xff1f; 当我们频繁地使用用多表查询和复合查询出的结果时&#xff0c;就需要频繁的使用…

Python中的HTTP协议

文章目录 一. 网址URL二. HTTP协议1. HTTP协议的概念2. HTTP协议的作用3. HTTP请求报文与响应报文① HTTP请求报文Ⅰ. GET请求报文格式Ⅱ. GET请求报文分析Ⅲ. POST请求报文格式Ⅳ. POST请求报文分析Ⅴ. GET与POST请求报文总结 ② HTTP响应报文Ⅰ. HTTP响应报文格式Ⅱ. HTTP响应…

108. UE5 GAS RPG 实现地图名称更新和加载关卡

在这一篇里&#xff0c;我们将实现对存档的删除功能&#xff0c;在删除时会有弹框确认。接着实现获取玩家的等级和地图名称和存档位置&#xff0c;我们可以通过存档进入游戏&#xff0c;玩家在游戏中可以在存档点存储存档。 实现删除存档 删除存档需要一个弹框确认&#xff0…

DNS批量解析管理软件有什么用

在复杂的网络环境中&#xff0c;DNS批量解析管理软件犹如一把功能强大的钥匙&#xff0c;开启了高效网络管理的大门&#xff0c;为网络运营和维护带来了诸多便利。 1、对于网络服务提供商而言&#xff0c;DNS批量解析管理软件极大地提高了工作效率 传统的DNS解析管理方式在处…

IoT [remote electricity meter]

IoT [remote electricity meter] 物联网&#xff0c;远程抄表&#xff0c;电表数据&#xff0c;举个例子

sql数据库-排序查询-DQL

目录 语法 排序方式 举例 将表按年龄从小到大排序 将表按年龄从大到小排序 ​编辑 多重排序 将表按年龄升序&#xff0c;年龄相同按入职时间降序 语法 select * from 表名 order by 字段名1 排序方式1&#xff0c;字段2 排序方式2; 排序方式 升序&#xff1a;ASC&…

在spring boot工程中使用Filter时,@WebFilter 注解不生效的问题分析和解决方案

1. 问题描述 首先编写一个Filter类并通过Component放入spring容器中&#xff0c;通过实现jakarta.servlet中提供的Filter接口完成过滤器的创建&#xff0c;代码如下。 import jakarta.servlet.*; import jakarta.servlet.annotation.WebFilter; import org.springframework.st…

学习threejs,使用TWEEN插件实现动画

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.PLYLoader PLY模型加…

TypeScript在现代前端开发中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 TypeScript在现代前端开发中的应用 TypeScript在现代前端开发中的应用 TypeScript在现代前端开发中的应用 引言 TypeScript 概述…

CTF-Crypto-简单加密

打开首页看题目 描述看起来是一段乱码&#xff0c;拉入随波逐流&#xff0c;未解决 e6Z9i~]8R~U~QHE{RnY{QXg~QnQ{^XVlRXlp^XI5Q6Q6SKY8jUAA 观察字符串&#xff0c;末尾是AA&#xff0c;其中可能含有base64加密 找寻Ascll码表&#xff0c;发现A的Ascll是65&#xff0c;的Ascl…

MacOS下,如何在Safari浏览器中打开或关闭页面中的图片文字翻译功能

MacOS下&#xff0c;如何在Safari浏览器中打开或关闭页面中的图片文字翻译功能 在Mac上的Safari浏览器中&#xff0c;可以通过实况文本功能来实现图片中的文本翻译。关闭步骤具体步骤如下&#xff1a; 在浏览器地址栏&#xff0c;鼠标右击翻译按钮&#xff0c;然后点击“首选…

操作系统——虚拟存储器(含思维导图)

本教材为中国铁道出版社——操作系统&#xff08;第四版&#xff09;刘振鹏、张明、王煜著。本篇文章为第六章复习。 目录 思维导图&#xff1a; ​编辑一、虚拟存储器 1.理论基础 2.定义 二、分页虚拟存储管理 1.基本原理 2.缺页中断 3.页面置换 &#xff08;1&…