Hooks实现原理与自定义Hooks
React Hooks 是 React 16.8 引入的一种机制,允许在函数组件中使用状态(state)、副作用(effect)等功能,而无需编写 class 组件。其核心原理是通过闭包和链表结构,在 React 的 Fiber 架构中管理组件的状态和副作用。(febook.hzfe.org)
🧩 Hooks 的基本原理
-
Hooks 是特殊的函数
Hooks 是一些特殊的函数,如useState
、useEffect
等,它们允许在函数组件中“钩入” React 的特性。例如,useState
允许函数组件拥有状态,而useEffect
处理副作用。 -
通过链表存储 Hooks
在 React 内部,每个函数组件对应一个 Fiber 节点,Fiber 节点的memoizedState
属性指向一个单向链表,链表中的每个节点代表一个 Hook。这种结构确保了 Hooks 的调用顺序,从而在每次渲染时正确地关联状态。 -
使用闭包保存状态
Hooks 利用 JavaScript 的闭包特性,在组件的多次渲染之间保持状态。例如,useState
返回的状态值和更新函数通过闭包与组件的渲染周期关联,从而在状态更新时触发重新渲染。
🔄 Hooks 的执行流程
-
初始化阶段
在组件首次渲染时,React 会为每个 Hook 创建一个 Hook 对象,并将其添加到 Fiber 节点的 Hooks 链表中。 -
更新阶段
在组件重新渲染时,React 会按照 Hooks 的调用顺序遍历 Hooks 链表,更新每个 Hook 的状态。 -
副作用处理
对于useEffect
等副作用 Hook,React 会在渲染后执行其回调函数,并根据依赖项数组判断是否需要重新执行副作用。
⚠️ 使用 Hooks 的注意事项
-
只能在函数组件或自定义 Hook 中调用 Hooks
Hooks 只能在函数组件或自定义 Hook 的顶层调用,不能在普通函数、条件语句或循环中调用。(sylvenas.github.io) -
保持 Hooks 的调用顺序一致
由于 Hooks 的状态依赖于调用顺序,必须确保每次渲染时 Hooks 的调用顺序不变。
🛠️ 模拟实现一个简化版的 useState
以下是一个简化的 useState
实现,用于理解其基本原理:(febook.hzfe.org)
let state;
function useState(initialValue) {state = state || initialValue;function setState(newValue) {state = newValue;render(); // 触发重新渲染}return [state, setState];
}
在这个示例中,state
变量通过闭包在多次渲染之间保持其值。setState
函数更新状态并触发重新渲染。(sylvenas.github.io)
如果您对 Hooks 的实现原理有更深入的兴趣,推荐阅读以下资源:
- React Hooks 原理剖析 - 知乎专栏
- React Hooks 原理及实现
- React Hooks 实现原理| HZFE - 剑指前端Offer
这些文章提供了更详细的解释和示例,帮助您深入理解 React Hooks 的工作机制。
Hooks实现原理详解
- Hooks的底层存储与执行逻辑
React Hooks的状态管理依赖于Fiber架构中的链表结构。每个函数组件对应的Fiber节点通过memoizedState
属性维护一个Hook链表,用于记录所有Hooks的调用顺序和状态。
• 首次渲染(Mount阶段):
调用useState
、useEffect
等Hooks时,React会按顺序创建Hook对象(包含memoizedState
、queue
、next
等属性),并构建链表。例如,useState
的初始值会被存储在memoizedState
中,queue
用于保存更新队列。
• 更新阶段(Update阶段):
React通过遍历Hook链表,按顺序复用之前创建的Hook对象,并基于新的依赖或状态执行更新逻辑。
- Hook链表的结构
每个Hook对象的结构如下:
{memoizedState: any, // 当前状态值(如useState的值、useEffect的依赖数组)baseQueue: Update, // 待处理的更新队列(如useState的setState调用)next: Hook | null // 指向下一个Hook的指针
}
例如,组件中连续调用useState
、useEffect
、useRef
时,会生成如下链表:
fiber.memoizedState → useState → useEffect → useRef → null
关键限制:Hooks必须在函数组件顶层调用,不可嵌套在条件/循环中,否则链表顺序会错乱导致状态错位。
依赖项更新机制
依赖项(如useEffect
的第二个参数)通过浅比较(Shallow Comparison)判断是否需要触发更新:
-
依赖项未变化:跳过副作用执行,优化性能。
-
依赖项变化:销毁旧副作用(如清除定时器),执行新副作用。
-
动态依赖策略:
• 自动化更新:通过工具检测依赖版本变化(如npm outdated
)。• 智能回滚:若新版本导致异常,自动回退到稳定版本。
自定义Hooks实现示例
- useFetch(数据请求)
import { useState, useEffect } from 'react';function useFetch(url) {const [data, setData] = useState(null);const [loading, setLoading] = useState(true);const [error, setError] = useState(null);useEffect(() => {fetch(url).then(res => res.json()).then(data => {setData(data);setLoading(false);}).catch(err => {setError(err);setLoading(false);});}, [url]); // 依赖项为url,url变化时重新请求return { data, loading, error };
}
使用场景:封装通用数据请求逻辑,避免组件冗余代码。
- useLocalStorage(本地存储同步)
function useLocalStorage(key, initialValue) {const [value, setValue] = useState(() => {const stored = localStorage.getItem(key);return stored ? JSON.parse(stored) : initialValue;});useEffect(() => {localStorage.setItem(key, JSON.stringify(value));}, [key, value]); // 依赖项变化时同步到存储return [value, setValue];
}
功能:将状态与localStorage
自动同步,提升数据持久化能力。
- useDebounce(防抖)
function useDebounce(value, delay = 500) {const [debouncedValue, setDebouncedValue] = useState(value);useEffect(() => {const timer = setTimeout(() => {setDebouncedValue(value);}, delay);return () => clearTimeout(timer); // 清理旧定时器}, [value, delay]); return debouncedValue;
}
应用场景:输入框搜索联想,避免频繁触发请求。
总结
• Hooks原理:依赖Fiber架构的链表结构,按顺序管理状态和副作用。
• 链表存储:通过memoizedState
维护Hook调用顺序,确保状态一致性。
• 依赖更新:浅比较优化性能,支持动态策略(如自动化检测和回滚)。
• 自定义Hooks:通过组合内置Hooks,封装可复用的业务逻辑(如数据请求、本地存储)。
通过理解这些机制,开发者可以更高效地设计复杂组件并优化性能。
相关文章:
Hooks实现原理与自定义Hooks
React Hooks 是 React 16.8 引入的一种机制,允许在函数组件中使用状态(state)、副作用(effect)等功能,而无需编写 class 组件。其核心原理是通过闭包和链表结构,在 React 的 Fiber 架构中管理组…...
【NLP】35. 构建高质量标注数据
如何构建高质量标注数据?大语言模型背后的那只“看不见的手” 在讨论大语言模型(LLM)性能突破时,人们总是聚焦在模型参数、结构设计和训练技巧上。但真正懂行的人都知道——再好的模型也离不开一手好数据,尤其是那些“…...
2024CCPC吉林省赛长春邀请赛 Java 做题记录
目录 I. The Easiest Problem G. Platform Game L. Recharge E. Connected Components I. The Easiest Problem 签到题 直接输出 21 即可 // github https://github.com/Dddddduo // github https://github.com/Dddddduo/acm-java-algorithm // github https://github.com/…...
黑马程序员C++2024新版笔记 第三章 数组
1.数组定义 数组是一批相同类型的元素(element)的集合组成的数据结构。 声明语法: <数据类型> <数组名> [<数组长度>] int v[6] // 声明了可以存放6个int数字的数组 数组的每个元素有编号,称之为下标索引…...
Golang的网络安全策略实践
Golang的网络安全策略实践 一、理解网络安全的重要性 当今的网络环境中,安全问题日益突出,各种类型的攻击如雨后春笋般涌现,给个人和组织的信息资产造成了严重威胁。因此,制定和实施有效的网络安全策略至关重要。 二、Golang在网络…...
SAP学习笔记 - 开发13 - CAP 之 添加数据库支持(Sqlite)
上一章学习了CAP开发准备,添加Service。 SAP学习笔记 - 开发12 - CAP 之 开发准备,添加服务-CSDN博客 本章继续学习CAP开发 - 添加数据库支持(Sqlite)。 目录 1,数据库准备 - H2 内存数据库 - Sqlite数据库 a&…...
DRIVEGPT4: 通过大语言模型实现可解释的端到端自动驾驶
《DriveGPT4: Interpretable End-to-End Autonomous Driving via Large Language Model》 2024年10月发表,来自香港大学、浙江大学、华为和悉尼大学。 多模态大型语言模型(MLLM)已成为研究界关注的一个突出领域,因为它们擅长处理…...
LLM最后怎么输出值 解码语言模型:从权重到概率的奥秘
LM Head Weights(语言模型头部权重):左侧的“LM Head Weights”表示语言模型头部的权重矩阵,它是模型参数的一部分。权重矩阵与输入数据进行运算。Logits(未归一化对数概率):经过与LM Head Weig…...
Better Faster Large Language Models via Multi-token Prediction 原理
目录 模型结构: Memory-efficient implementation: 实验: 1. 在大规模模型上效果显著: 2. 在不同类型任务上的效果: 为什么MLP对效果有提升的几点猜测: 1. 并非所有token对生成质量的影响相同 2. 关…...
【NLP】34. 数据专题:如何打造高质量训练数据集
构建大语言模型的秘密武器:如何打造高质量训练数据集? 在大语言模型(LLM)如 GPT、BERT、T5 爆发式发展的背后,我们常常关注模型架构的演化,却忽视了一个更基础也更关键的问题:训练数据从哪里来…...
uniapp 微信小程序 获取openId
嗨,我是小路。今天主要和大家分享的主题是“uniapp 微信小程序 获取openId”。 一、主要属性 1.uni.login 二、实例代码 1、前端代码 uni.login({provider: weixin,success: (res) > {uni.showLoading({title: 登录中...,mask: true})let code res.…...
企业标准信息公共服务平台已开放标准通编辑器访问入口
标准通 数字化标准编辑器 专业、高效、便捷 企业标准信息公共服务平台 近日,企业标准信息公共服务平台已开放标准通编辑器访问入口,可进入官网指定版块使用! 核心功能亮点 解决企业痛点 传统标准编制,需反复核对格式、逐条…...
小米MUJIA智能音频眼镜来袭
智能眼镜赛道风云再起,小米新力作MIJIA智能音频眼镜2正式亮相,引发市场热议。 这款产品在设计和功能上都有显著提升,为用户带来更舒适便捷的佩戴体验,同时也标志着小米在智能眼镜领域的持续深耕。 轻薄设计,舒适体验 …...
Node.js 实战八:服务部署方案对比与实践
你开发好了接口,准备上线,然后开始犹豫: “直接 node app.js 启就行了吗?” “要不要用 PM2?听说 Docker 更稳?” “Serverless 是不是就不用管服务器了?” 部署是从“能运行”到“能长久运行”…...
地下水安全监测实施方案
一、方案目标 本方案的核心目标在于构建一个全方位、科学严谨且高效运转的地下水监测体系,旨在实现对地下水资源全方位的动态监测、科学化的管理和有效的保护。监测的具体目标涵盖了地下水位、流量以及水质等多个关键性指标,通过精准的数据采集和分析&am…...
HTTP由浅入深
概述 超文本传输协议(HTTP, Hypertext Transfer Protocol) 是一种用于传输超媒体文档(例如 HTML)的应用层协议。它最初被设计用于 Web 浏览器与 Web 服务器之间的通信,但也广泛应用于其他客户端与服务器的交互。 HTT…...
Conda 环境下安装 GCC 和 glibc (crypt.h) 教程
Conda 环境下安装 GCC 和 glibc (crypt.h) 教程 由于运行Low-Light Image Enhancement via Structure Modeling and Guidance原始论文代码,发现服务器的gcc版本太老,没法运行。同时缺少libxcrypt (crypt.h),不得不询问gpt进行解答。发现可以…...
C++面试3——const关键字的核心概念、典型场景和易错陷阱
const关键字的核心概念、典型场景和易错陷阱 一、const本质:类型系统的守护者 1. 与#define的本质差异 维度#defineconst编译阶段预处理替换编译器类型检查作用域无作用域(全局污染)遵循块作用域调试可见性符号消失保留符号信息类型安全无类…...
超小多模态视觉语言模型MiniMind-V 训练
简述 MiniMind-V 是一个超适合初学者的项目,让你用普通电脑就能训一个能看图说话的 AI。训练过程就像教小孩:先准备好图文材料(数据集),教它基础知识(预训练),再教具体技能…...
深入理解仿函数(Functors):从概念到实践
文章目录 1. 什么是仿函数?2. 仿函数与普通函数的区别3. 标准库中的仿函数4. 仿函数的优势4.1 状态保持4.2 可定制性4.3 性能优势 5. 现代C中的仿函数5.1 Lambda表达式5.2 通用仿函数 6. 仿函数的高级应用(使用C2020标准库及以上版本)6.1 函数…...
第二届parloo杯的RSA_Quartic_Quandary
(害,还是太菜了,上去秒了一道题之后就动不了了,今晚做个记录,一点点的往回拾起吧) # from Crypto.Util.number import getPrime, bytes_to_long # import math # # FLAG b************** # # # def gene…...
团队氛围紧张,如何提升工作积极性?
当团队氛围长期处于紧张状态时,员工的积极性、创造力和凝聚力会显著下降。要有效提升工作积极性,应从建设心理安全环境、优化管理沟通方式、提升认可与激励机制、加强情感联结与归属感等方面系统改善。其中,建设心理安全环境是最重要的基础&a…...
vuex的基本使用
个人简介 👨💻个人主页: 魔术师 📖学习方向: 主攻前端方向,正逐渐往全栈发展 🚴个人状态: 研发工程师,现效力于政务服务网事业 🇨🇳人生格言&…...
chrome因使用selenium无图模式导致不再加载图片问题解决
因为使用了selenium的无图模式访问chrome的本地用户数据导致正常使用chrome访问网页时图片不加载。现在页面出现验证码,验证码显示不了。 第一步:关闭所有chrome 第二步:找到Perferences文件 文件的目录为:C:\Users\用户名\AppDa…...
并发编程(5)
抛异常时会释放锁。 当线程在 synchronized 块内部抛出异常时,会自动释放对象锁。 public class ExceptionUnlockDemo {private static final Object lock new Object();public static void main(String[] args) {Thread t1 new Thread(() -> {synchronized …...
自己拥有一台服务器可以做哪些事情
上大学时候,买了自己的第一台服务器在HoRain Cloud上,结果没有好好利用,刚工作时候,又买了一台HoRain Cloud服务器,就想着好好利用。 可以搭建一些学习环境,比如说数据库,gitlab什么的 …...
Node.js聊天室开发:从零到上线的完整指南
为让你全面了解Node.js聊天室开发,我会先介绍开发背景与技术栈,再按搭建项目、实现核心功能、部署上线的流程展开,还会分享优化思路。 Node.js聊天室开发实战:从入门到上线 在即时通讯日益普及的今天,基于Node.js搭建…...
Unity 如何使用Timeline预览、播放特效
在使用unity制作和拟合动画时,我们常用到Timeline,前后拖动滑轨,预览动画正放倒放非常方便。如果我们想对特效也进行这个操作,可以使用下文的步骤。 至此,恭喜你又解锁了一个新的技巧。如果我的分享对你有帮助…...
实物工厂零件画图案例(下)
文章目录 总练习模块文章索引气动顶针轴直线轴承座法兰盘平皮带中空传动轴减速机V带轮减速机箱体 简介:点击此处可以下载该文章的案例模型,加上这篇文章总共有七篇文章是用来练习solidworks软件应用与建模思路的,大概有30多个案例模型&#x…...
esp32课设记录(五)整个项目开源github
我把该项目开源到了github:https://github.com/whyovo/ESP32_course_project 以下是readme文档: ESP32 课设 项目概述 这是一个基于ESP32的课设,实现了多种功能模式的集成,包括信息显示、图片展示、MQTT通信、摩尔斯电码处理以…...
力扣每日一题5-19
class Solution { public String triangleType(int[] nums) { Arrays.sort(nums); if (nums[0] nums[1] < nums[2]) return “none”; if (nums[0] nums[1] && nums[1] nums[2]) return “equilateral”; if (nums[0] nums[1] || nums[1] nums[2]) return “is…...
CI/CD 深度实践:灰度发布、监控体系与回滚机制详解
CI/CD 深度实践:灰度发布、监控体系与回滚机制详解 一、引言 在现代软件开发中,持续集成与持续交付(CI/CD)是加快交付速度、提升质量的关键。面对复杂的分布式系统和海量用户,如何安全、快速地发布新版本,…...
【日常笔记】wps如何将值转换成东西南北等风向汉字
在WPS表格中,若要将数值(如角度值)转换成“东、南、西、北”等风向汉字,可通过以下步骤结合自定义函数或条件判断实现: 一、wps如何将值转换 方法一:使用LOOKUP函数(简化公式)&…...
RabbitMQ的简介
三个概念 生产者:生产消息的服务消息代理:消息中间件,如RabbitMQ消费者:获取使用消息的服务 消息队列到达消费者的两种形式 队列(queue):点对点消息通信(point-to-point) 消息进入队…...
中职大数据实验室解决方案分享
第1部分概述 1.1政策背景 2021年3月,教育部印发《职业教育专业目录(2021年)》,共设置19个专业大类、97个专业类、1349个专业。新版《目录》聚焦推进数字化升级改造,构建未来技术技能,优化和加强了5G、人工智能、大数据、云计算、…...
阿里云web端直播(前端部分)
阿里云:Web播放器快速接入_视频点播(VOD)-阿里云帮助中心 import Aliplayer from aliyun-aliplayerimport aliyun-aliplayer/build/skins/default/aliplayer-min.css<div id"J_prismPlayer" style"width: 300px; height: 300px;" />var …...
从虚拟仿真到行业实训再到具身智能--华清远见嵌入式物联网人工智能全链路教学方案
2025年5月23-25日,第63届中国高等教育博览会(高博会)将在长春中铁东北亚国际博览中心举办。作为国内高等教育领域规模大、影响力广的综合性展会,高博会始终聚焦教育科技前沿,吸引全国高校管理者、一线教师、教育科技企…...
阿里云国际站与国内站:局势推进中的多维差异
在当今数字化浪潮席卷全球,云计算成为企业与开发者关键助力的局势下,阿里云作为行业翘楚,其国际站与国内站备受关注。两者虽同宗同源,却在诸多方面存在着显著差异,这些差异犹如隐藏在幕后的齿轮,悄然影响着…...
Docker项目部署深度解析:从基础命令到复杂项目部署
Docker项目部署深度解析:从基础命令到复杂项目部署 注:根据黑马程序员javawebAI视频课程总结: 视频地址 详细讲义地址 一、传统部署困境与Docker破局之道 在传统Linux部署场景中,新手常被三大难题困扰: 命令记忆负…...
reserve学习笔记(花指令)
这是闲来无事逛博客时看到的一篇相关文章,觉得挺有意思。 定义 首先花指令其实就是没有用的指令(垃圾指令),它穿插在真正的代码中,会导致反编译时出现问题,从而会影响我们的静态分析 分类以及讲解 花指…...
docker运行Redis
创建目录 mkdir -p /home/jie/docker/redis/{conf,data,logs}添加权限 chmod -R 777 /home/jie/docker/redis创建配置文件 cat > /home/jie/docker/redis/conf/redis.conf << EOF # 基本配置 bind 0.0.0.0 protected-mode yes port 6379# 安全配置 密码是root require…...
Django 项目中,将所有数据表注册到 Django 后台管理系统
在 Django 项目中,将所有数据表注册到 Django 后台管理系统中需要为每个模型(Model)创建一个对应的 ModelAdmin 类,并在 admin.py 文件中注册这些模型。以下是一个详细的步骤指南: 确保你的模型已定义 首先,确保你已经在 models.py 文件中定义了所有的数据模型。例如:py…...
pyspark测试样例
from pyspark.sql import SparkSession from pyspark.sql.functions import col, lit, concat 创建 SparkSession spark SparkSession.builder.appName(“SparkSQLExample”).getOrCreate() 创建 DataFrame(可以是从 CSV、JSON 等文件读取) data […...
Python学习笔记--使用Django操作mysql
注意:本笔记基于python 3.12,不同版本命令会有些许差别!!! Django 模型 Django 对各种数据库提供了很好的支持,包括:PostgreSQL、MySQL、SQLite、Oracle。 Django 为这些数据库提供了统一的调…...
HarmonyOS Next应用分层架构下组件封装开发实践
基于鸿蒙应用分层架构的ArkUI组件封装实践 在鸿蒙应用开发中,合理利用 ArkUI 组件进行封装,可以实现代码复用,提升开发效率。本文将结合鸿蒙应用分层架构的特点,详细探讨几个典型的 ArkUI 组件封装场景及其实现方案。 华为鸿蒙应…...
全能视频处理工具介绍说明
软件介绍 本文介绍的软件是FFmpeg小白助手,它是一款视频处理工具。 使用便捷性 这款FFmpeg小白助手无需安装,解压出来就能够直接投入使用。 主要功能概述 该工具主要具备格式转换、文件裁剪、文件压缩、文件合并这四大功能。 格式转换能力 软件支持…...
CSS实现过多的文本进行省略号显示
单行文本省略 .ellipsis {white-space: nowrap; /* 禁止换行 */overflow: hidden; /* 溢出内容隐藏 */text-overflow: ellipsis; /* 溢出部分显示为省略号 */width: 200px; /* 必须设置宽度 */ } 多行文本省略(跨浏览器方案)…...
十三、Hive 行列转换
作者:IvanCodes 日期:2025年5月19日 专栏:Hive教程 在Hive中,数据的形态转换是数据清洗、分析和报表制作中的核心环节。行列转换尤为关键,它能将数据从一种组织形式变为另一种,以适应不同的业务洞察需求。本…...
Django之验证码功能
验证码功能 目录 1.绘制验证码 2.在登录页面里面实现验证码的功能 3.代码展示集合 这篇文章, 内容不是很多, 不过验证码, 是在网页里面比较常见的功能, 所有我们还是要掌握它!!! 一、绘制验证码 绘制验证码, 我们需要用到图像, 然后在…...
代码随想录算法训练营 Day51 图论Ⅱ岛屿问题Ⅰ
图论 题目 99. 岛屿数量 使用 DFS 实现方法 判断岛屿方法 1. 遍历图,若遍历到了陆地 grid[i][j] 1 并且陆地没有被访问,在这个陆地的基础上进行 DFS 方法,或者是 BFS 方法 2. 对陆地进行 DFS 的时候时刻注意以访问的元素添加访问标记 //…...