当前位置: 首页 > news >正文

React 中 useCallback 的基本使用和原理解析

React 中 useCallback 的基本使用方法

useCallback 是 React 的一个核心 Hook,用于​缓存函数定义​,避免组件重新渲染时重复创建函数实例。以下是其基本使用方法:

1. 基本语法

const memoizedCallback = useCallback(() => {// 函数逻辑 (例如更新状态、调用API等)doSomething(a, b);},[a, b] // 依赖项数组
);
  • 第一个参数​:需要缓存的函数。
  • 第二个参数​:依赖项数组(Dependency Array),当数组中的变量变化时,函数会重新创建。

2. 核心作用

  • 避免不必要的函数重建​:默认情况下,组件每次渲染都会创建新的函数实例,使用 useCallback 后可复用函数。
  • 优化子组件渲染​:当缓存的函数作为 props 传递给子组件(配合 React.memo)时,可避免子组件不必要的重渲染​。

3. 使用示例

import React, { useState, useCallback } from 'react';function Counter() {const [count, setCount] = useState(0);// 缓存函数:依赖项为空数组,函数只创建一次const increment = useCallback(() => {setCount(prev => prev + 1); // 使用函数式更新避免闭包问题}, []);return (<div><p>Count: {count}</p><button onClick={increment}>+1</button></div>);
}
  • 依赖项 [] 表示函数仅在组件初次渲染时创建。
  • 使用 setCount(prev => prev + 1) 替代 setCount(count + 1) 可避免闭包陷阱(函数捕获过时状态)​。

4. 适用场景

useCallback,本质上是用于缓存函数。

如果函数,是以props的方式,传递给子组件,为了每次避免子组件的渲染,建议使用useCallback进行包裹。

但是每一次,使用useCallback,我们考虑的首要问题是,这样真的优化了组件的性能吗?其实大多数场景,如果不是类似列表渲染的场景,这样不一定会优化了性能。

也就是,函数作为props传递给性能敏感的子组件的场景,才是使用useCallback的时候。

useCallback 的原理解析

  • useCallback 的主要目的是在依赖项不变的情况下,返回同一个函数引用,避免函数重复创建,从而优化性能。
  • useCallback它会在首次渲染时(或依赖项变化时)创建一个新的函数,并将其缓存起来。在后续渲染中,如果依赖项没有变化,则返回缓存的函数;否则,就重新创建函数并更新缓存。
  • 简易的伪代码,可能如下所示
let lastDeps; // 上一次的依赖项
let lastCallback; // 上一次缓存的函数function useCallback(callback, deps) {if (lastDeps === undefined) {// 第一次调用lastDeps = deps;lastCallback = callback;return callback;}// 检查依赖项是否变化const hasChanged = deps.some((dep, index) => dep !== lastDeps[index]);if (hasChanged) {lastDeps = deps;lastCallback = callback;}return lastCallback;
}

每次掉用useCallback,返回的函数,取决于依赖项有没有发生变化。

React内部是咋样的呢?

1、Fiber 节点存储机制

React 在 Fiber 节点(组件实例对应的数据结构)中维护一个 memorizedState 链表,专门存储 Hooks 状态。

function updateCallback(callback, deps) {const hook = updateWorkInProgressHook(); // 获取当前 Hook 节点const nextDeps = deps === undefined ? null : deps;const prevState = hook.memoizedState;     // 读取缓存的上次状态// 依赖项对比:使用浅比较(shallow equal)if (prevState !== null && areHookInputsEqual(nextDeps, prevState[1])) {return prevState[0]; // 返回缓存的函数}//  依赖变化:缓存新函数hook.memoizedState = [callback, nextDeps];return callback;
}

2、依赖项对比算法

源码中的 areHookInputsEqual 对依赖数组进行浅比较(类似 Object.is):

function areHookInputsEqual(nextDeps, prevDeps) {if (prevDeps === null) return false;for (let i = 0; i < prevDeps.length; i++) {if (!Object.is(nextDeps[i], prevDeps[i])) {return false;}}return true;
}

这种优化避免了深度比较的性能损耗

http://www.jsqmd.com/news/31621/

相关文章:

  • SpringCloud和K8s实现的微服务各有什么优缺点
  • Zabbix告警:value cache working in low memory mode
  • 计算机导论
  • go语言实现腾讯股票获取示例(并发)
  • 出海 AI 公司招 Java 大佬|北京
  • 在欧拉系统上安装openGauss数据库
  • 2025.11.4总结
  • 医疗非结构化数据价值挖掘:文档抽取技术的工作原理与场景实践
  • 18、Flink CDC监听MySQL-Binlog实现数据监听
  • Ai元人文构想并不神秘—系统化流程图
  • 2025 年 11 月 EVA 厂家推荐排行榜,eva塑料,eva板材,eva卷材,eva发泡材料,eva橡塑制品公司推荐
  • 2025 年 11 月防爆电磁阀厂家推荐排行榜,气动防爆电磁阀,先导式防爆电磁阀,直动式防爆电磁阀,不锈钢防爆电磁阀,禁铜禁锌防爆电磁阀公司推荐
  • 11.04
  • 20251104 正睿
  • 【做题记录】多校-dp
  • CSP-S 题解反思考场游记
  • 新学期每日总结(第19天)
  • 2025 年 11 月扑灭司林厂家推荐排行榜:专业杀虫剂,高效农药,卫生防疫用药,农业喷洒用药源头厂家精选!
  • 2025 年 11 月高压清洗机厂家推荐排行榜,超高压清洗机组,超高压水清洗设备,超高压清洗装置,工业超高压清洗设备公司精选
  • Centos7安装新版本python3.10
  • 2025 年 11 月高温轴承厂家权威推荐榜:耐高温轴承,真空高温轴承,窑炉高温轴承,BOPP链夹高温轴承,高温调心球轴承,高温关节轴承,高温滚针轴承,高温角接触轴承,高温圆柱滚子轴承公司推荐
  • 2025 年 11 月不干胶轮转机厂家推荐排行榜,商标不干胶轮转机,高速轮转印刷设备,高效稳定生产解决方案
  • swagger-typescript-api
  • HAL库DMA框架
  • 2025 年 11 月电线电缆厂家推荐排行榜,国标电线电缆,中缆电线电缆,工程电线电缆,环保电线电缆,家用电线电缆,工业电线电缆,光伏电线电缆,耐火电线电缆公司推荐
  • 2025 年 11 月清洗机厂家推荐排行榜,全自动/工业/零排放/双溶剂/碳氢/改性醇/真空/全密闭清洗机设备公司精选
  • 2025 年 11 月电线电缆厂家推荐排行榜,电力电缆,控制电缆,通信电缆,阻燃电缆,高压电缆公司推荐
  • 2025 年 11 月电磁阀线圈厂家推荐排行榜,电磁线圈,电磁铁线圈,小型电磁线圈,微型线圈,汽车电磁线圈,车用感应线圈,防爆线圈,防爆电磁线圈,直流电磁线圈,电磁线圈定制公司推荐
  • 2025 年 11 月潜水泵厂家推荐排行榜,新型潜水泵,节能潜水泵,低噪声潜水泵,超低压潜水泵,防爆潜水泵,高压潜水泵,防腐潜水泵公司推荐
  • 2025 年 11 月消杀药剂厂家推荐排行榜,扑灭司林/5%扑灭司林,苯甲酸苄酯/25%苯甲酸苄酯,15%胺氯菊百灭宁,疥螨,阴虱,科灭达公司推荐