为什么避免在循环、条件或嵌套函数中调用 Hooks
为什么避免在循环、条件或嵌套函数中调用 Hooks
为了确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确。
我们可以在单个组件中使用多个 State Hook 或 Effect Hook:
function Form() {// 1. 使用变量名为 name 的 stateconst [name, setName] = useState('Mary');// 2. 使用 effect 以保存 form 操作useEffect(function persistForm() {localStorage.setItem('formData', name);});// 3. 使用变量名为 surname 的 stateconst [surname, setSurname] = useState('Poppins');// 4. 使用 effect 以更新标题useEffect(function updateTitle() {document.title = name + ' ' + surname;});// ...
}
那么 React 怎么知道哪个 state 对应哪个 useState?答案是 React 靠的是 Hook 调用的顺序。
let hookStates = []; // 放着此组件的所有的hooks数据
let hookIndex = 0; // 代表当前的hooks的索引
function useState(initialState){// 如果有老值取老值,没有取默认值hookStates[hookIndex] = hookStates[hookIndex] || initialState;// 暂存索引let currentIndex = hookIndex;//setState方法,将当前值置为新值function setState(newState){hookStates[currentIndex] = newState;//置完新值,立刻触发渲染render();}return [hookStates[hookIndex++], setState];
}
因为我们的示例中,Hook 的调用顺序在每次渲染中都是相同的,所以它能够正常工作:
// ------------
// 首次渲染
// ------------
useState('Mary') // 1. 使用 'Mary' 初始化变量名为 name 的 state
useEffect(persistForm) // 2. 添加 effect 以保存 form 操作
useState('Poppins') // 3. 使用 'Poppins' 初始化变量名为 surname 的 state
useEffect(updateTitle) // 4. 添加 effect 以更新标题// -------------
// 二次渲染
// useState - 不再使用传入的默认值,而是返回上次渲染时存储的状态值。
// useEffect 首先运行之前 useEffect 的清理函数(如果有的话),然后再运行新的副作用函数。
// -------------
useState('Mary') // 1. 读取变量名为 name 的 state(Mary参数被忽略)
useEffect(persistForm) // 2. 清除并替换上一次 form 的 effect
useState('Poppins') // 3. 读取变量名为 surname 的 state(Poppins参数被忽略)
useEffect(updateTitle) // 4. 清除并替换上一次更新标题的 effect// ...
useEffect Hook有什么作用?如何理解 替换与清除?
告诉 React 需要在完成DOM更新之后(渲染之后)执行一些“副作用”(如数据获取、手动更改DOM、设置订阅或者清除上一次的副作用等)。
useEffect(persistForm) 在首次渲染时添加了一个副作用,即 persistForm 函数。然后,在随后的组件更新(第二次渲染)中,相同的 useEffect(persistForm) 调用会首先清除前一次的副作用(如果 persistForm 返回了一个清除函数的话),然后再执行新的 persistForm 副作用。
这样确保了副作用是最新的,并且在多次渲染之间不会有冲突。这也是为什么我们说第二次和随后的渲染是“替换”前一次的副作用。
只要 Hook 的调用顺序在多次渲染之间保持一致,React 就能正确地将内部 state 和对应的 Hook 进行关联。但如果我们将一个 Hook (例如 persistForm effect) 调用放到一个条件语句中会发生什么呢?
比如:
// ???? 在条件语句中使用 Hook 违反第一条规则if (name !== '') {useEffect(function persistForm() {localStorage.setItem('formData', name);});}
在第一次渲染中 name !== ‘’ 这个条件值为 true,所以我们会执行这个 Hook。但是下一次渲染时我们可能清空了 name,表达式值变为 false。此时的渲染会跳过该 Hook,Hook 的调用顺序发生了改变:
useState('Mary') // 1. 读取变量名为 name 的 state(参数被忽略)
// useEffect(persistForm) // ???? 此 Hook 被忽略!
useState('Poppins') // ???? 2(之前为 3)。读取变量名为 surname 的 state 失败
useEffect(updateTitle) // ???? 3 (之前为 4)。替换更新标题的 effect 失败
-
第一次调用
useState('Mary'),此时hookIndex=0,状态被存储在hookStates[0]。 -
然后我们跳过
useEffect(persistForm)。 -
接下来的
useState('Poppins')会使用hookIndex=1,但在上一次渲染中,它使用了hookIndex=2。这会导致 surname 的状态从错误的位置获取。 -
以此类推,后续的
useEffect(updateTitle)也会使用错误的索引。
相关文章:
为什么避免在循环、条件或嵌套函数中调用 Hooks
为什么避免在循环、条件或嵌套函数中调用 Hooks 为了确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useState 和 useEffect 调用之间保持 hook 状态的正确。 我们可以在单个组件中使用多个 State Hook 或 Effect Hook: function Form…...
自然语言处理---Transformer机制详解之BERT模型特点
1 BERT的优点和缺点 1.1 BERT的优点 通过预训练, 加上Fine-tunning, 在11项NLP任务上取得最优结果.BERT的根基源于Transformer, 相比传统RNN更加高效, 可以并行化处理同时能捕捉长距离的语义和结构依赖.BERT采用了Transformer架构中的Encoder模块, 不仅仅获得了真正意义上的b…...
c语言基础:L1-048 矩阵A乘以B
给定两个矩阵A和B,要求你计算它们的乘积矩阵AB。需要注意的是,只有规模匹配的矩阵才可以相乘即若A有Ra行、Ca列,B有Rb行、Cb列,则只有Ca与Rb相等时,两个矩阵才能相乘。 输入格式: 输入先后给出…...
asp.net乒乓球场地管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio
一、源码特点 asp.net乒乓球场地管理系统是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为sqlserver2008,使用c#语 言开发 asp.net 乒乓球场地管理系统 二…...
git仓库中增加子仓库
在 Git 中包含另一个 Git 仓库通常使用 Git 子模块(Git Submodule)来实现。子模块允许你在一个 Git 仓库中包含另一个 Git 仓库,从而在一个仓库中管理多个相关但独立的项目。 以下是如何将一个 Git 仓库包含为另一个 Git 仓库的子模块的步骤…...
html中公用css、js提取、使用
前言 开发中,页面会有引用相同的css、js的情况,如需更改则每个页面都需要调整,重复性工作较多,另外在更改内容之后上传至服务器中会有缓存问题,特针对该情况对公用css、js进行了提取并对引用时增加了版本号 一、提取…...
Jprofiler V14中文使用文档
JProfiler介绍 什么是JProfiler? JProfiler是一个用于分析运行JVM内部情况的专业工具。 在开发中你可以使用它,用于质量保证,也可以解决你的生产系统遇到的问题。 JProfiler处理四个主要问题: 方法调用 这通常被称为"CPU分析"。方法调用可以通过不同的方式进行测…...
基于PHP的蛋糕甜品商店管理系统设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding) 代码参考数据库参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…...
DJYROS产品:基于DJYOS的国产自主割草机器人解决方案
基于都江堰泛计算操作系统的国产自主机器人操作系统即将发布…… 1、都江堰机器人操作系统命名:DJYROS 2、机器人算法:联合行业自主机器人厂家,构建机器人算法库。 3、机器人芯片:联合行业机器人AI芯片公司,构建专用…...
A预测蛋白质结构
基于AlphaFold2进行蛋白质结构预测的文章解析 RoseTTAFold: Tunyasuvunakool, K., Adler, J., Wu, Z. et al. Highly accurate protein structure prediction for the human proteome. Nature 596, 590–596 (2021) AlphaFold2: Accurate prediction of protein structures a…...
rust学习~slice迭代器
背景 pub fn iter(&self) -> Iter<_, T>查看Iter 结构体 pub struct Iter<a, T> whereT: a, {/* private fields */ }对迭代器求和 sum fn sum<S>(self) -> S whereSelf: Sized, // 该函数只能在具有已知大小的类型上调用S: Sum<Self::Item…...
python免杀初探
文章目录 loader基础知识loader参数介绍 evilhiding项目地址免杀方式修改加载器花指令混淆loader源码修改签名加壳远程条件触发修改ico的md5加密 loader基础知识 loader import ctypes #(kali生成payload存放位置) shellcode bytearray(b"shellc…...
OpenCV实现物体尺寸的测量
一 ,项目分析 物体尺寸测量的思路是找一个确定尺寸的物体作为参照物,根据已知的计算未知物体尺寸。 如下图所示,绿色的板子尺寸为220*300(单位:毫米),通过程序计算白色纸片的长度。 主要是通过…...
投资研报的优质网站
投资研报:https://www.zhihu.com/question/357713923/answer/2304672553...
每日刷题|贪心算法初识
食用指南:本文为作者刷题中认为有必要记录的题目 推荐专栏:每日刷题 ♈️今日夜电波:悬溺—葛东琪 0:34 ━━━━━━️💟──────── 3:17 …...
[python]如何操作Outlook实现邮件自动化
【背景】 邮件自动化存在很多需求场景,有的场景希望会出现Outlook窗口在发送前进行一下人工检查等等的人为干预,有的则希望定时直接发送,有的需要加附件等等。本篇讨论用Python覆盖这些Outlook邮件自动化场景的方法。 【解决方法】 首先Outlook和SMTP的邮件自动化方法所使…...
2008-2021年上市公司实体企业金融化程度测算数据(原始数据+stata代码)
2008-2021年上市公司实体企业金融化程度测算(原始数据stata代码) 1、时间:2008-2021年 2、指标:股票代码、年份、交易性金融资产、衍生金融资产、发放贷款及垫款净额、可供出售金融资产净额、持有至到期投资净额、长期债权投资净…...
day02_numpy_demo
Numpy Numpy的优势ndarray属性基本操作 ndarray.func() numpy.func()ndarray的运算:逻辑运算、统计运算、数组间运算合并、分割、IO操作、数据处理,不过这个一般使用的是pandas Numpy的优势 Numpy numerical数值化 python 数值计算的python库,用于快…...
LeetCode 414. Third Maximum Number【数组】简单
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...
FPGA时序分析与约束(6)——综合的基础知识
在使用时序约束的设计过程中,综合(synthesis)是第一步。 一、综合的解释 在电子设计中,综合是指完成特定功能的门级网表的实现。除了特定功能,综合的过程可能还要满足某种其他要求,如功率、操作频率等。 有…...
【AGI物流落地倒计时】:为什么2026年Q2成为企业接入自主决策物流AI的最后窗口期?
第一章:2026奇点智能技术大会:AGI与物流管理 2026奇点智能技术大会(https://ml-summit.org) AGI驱动的动态物流决策中枢 在2026奇点智能技术大会上,多家头部物流企业联合发布了基于自主推理架构(Autonomous Reasoning Architect…...
RKMEDIA VO图层配置与双屏显示实战
1. RKMEDIA VO模块基础解析 第一次接触RV1126/RV1109的双屏显示功能时,我也被各种专业术语搞得一头雾水。经过几个项目的实战,现在终于能把这个功能讲得通俗易懂了。RKMEDIA的VO(Video Output)模块本质上是对Linux DRM(…...
从电赛到实战:基于OpenMV与STM32的视觉追踪小车系统设计
1. 视觉追踪小车的核心设计思路 第一次接触视觉追踪小车是在大三的电赛备赛期间,当时看到学长做的自动跟随机器人特别酷,就决定自己动手做一个。经过两个月的折腾,终于实现了基于OpenMV和STM32的视觉追踪系统。这个项目的核心在于让机器像人眼…...
手把手教你用VMware Workstation 17 Pro给笔记本装个华为openEuler(附UKUI桌面安装避坑指南)
在VMware Workstation 17 Pro上体验openEuler:从安装到UKUI桌面的完整指南 最近两年,国产操作系统的发展势头越来越猛,不少技术爱好者都想亲自体验一下这些系统。作为华为推出的开源操作系统,openEuler凭借其出色的性能和丰富的生…...
材料科学正经历第4次方法论革命?——基于2026奇点大会278项AGI实验数据的颠覆性趋势研判
第一章:材料科学正经历第4次方法论革命?——基于2026奇点大会278项AGI实验数据的颠覆性趋势研判 2026奇点智能技术大会(https://ml-summit.org) 278项AGI驱动的材料发现实验揭示了一个结构性跃迁:传统“试错—表征—建模”闭环已被AGI原生工…...
毕业答辩PPT别再手动肝了!百考通AI十分钟自动生成高质量学术汇报稿
在经历了论文撰写、反复修改、查重降重的重重考验后,许多同学却在最后一道关卡——毕业答辩PPT的制作上,耗费了意想不到的巨大心力。你是否也曾面对空白的演示文稿绞尽脑汁:如何将数万字的论文浓缩成十几页幻灯片?怎样的排版才显得…...
从零到一:PrimeTime静态时序分析入门指南
从零到一:PrimeTime静态时序分析入门指南 在数字芯片设计的最后阶段,时序收敛往往是工程师们最头疼的问题之一。想象一下,当你精心设计的电路在仿真中表现完美,却因为时序问题无法通过物理实现,那种挫败感足以让任何工…...
如何在 Supabase 中安全实现用户“鼓掌”计数(防刷、防重放、防越权)
本文详解如何通过 rls 策略 合理数据建模,在 supabase 中安全实现用户交互式操作(如虚拟鼓掌),杜绝前端恶意请求篡改计数,兼顾安全性与可扩展性。 本文详解如何通过 rls 策略 合理数据建模,在 supab…...
从LCD到MicroLED:手把手拆解主流显示技术演进史,看懂未来屏幕长啥样
从LCD到MicroLED:手把手拆解主流显示技术演进史,看懂未来屏幕长啥样 每次点亮手机屏幕时,你有没有想过——这些色彩斑斓的像素点是如何从实验室走向我们掌心的?显示技术的进化就像一场接力赛,每一代技术都在解决前代的…...
别再踩坑了!ABAP里用CL_JAVA_SCRIPT调用JS计算MD5的完整流程(含中文UTF-8处理)
ABAP中通过JavaScript引擎实现跨平台MD5校验的完整实践指南 当ABAP系统需要与Java等外部系统进行数据校验时,标准函数MD5_CALCULATE_HASH_FOR_CHAR的结果差异常常让开发者陷入困境。本文将深入解析编码差异背后的本质原因,并提供一个基于CL_JAVA_SCRIPT…...
