react:hooks为什么不能写在条件语句里
背景
最近朋友在面试,说面试官问到了一个问题不会,说为什么 react hooks为什么不能写在条件语句里,今天我们来研究一下这个问题。
我们在来简单实现一个 useState:
const reRender = () => {stateIndex = -1 ReactDOM.render(<App/>,document.getElementById('root'))
}let stateQueue = []; // 用于存放每个useState返回值。
let stateIndex = -1; //给每个 useState的返回值一个序号。
function useState(initState) {stateIndex++;stateQueue[stateIndex] = stateQueue[stateIndex] || initState;const currentIndex = stateIndexfunction setState(newState) {stateQueue[currentIndex] = newState;reRender(); //组件重渲染}return [stateQueue[stateIndex],setState]
}
我们用上面写的 useState 来测试看看下面代码的执行过程
function RenderFunctionComponent() {const [name, setName] = useState("Lvan");const [age, setAge] = useState("0");return (<div>{name}</div><div>{age}</div><Button onClick={() => setName("Tom")}>name设置为Tom</Button>);
}
调用两次 useState 后:
stateQueue: ["Lvan", "0"]
stateIndex: 1
这时候点击按钮调用 setName,由于闭包的原因,当前这里的 currentIndex 为 0,然后触发了
stateQueue[0] = "Tom"
// reRender()
stateIndex = -1
ReactDOM.render(<App/>,document.getElementById('root'))
此时重新渲染,并且会重新调用一遍 useState,而这时 stateQueue 已经是 ["Tom", "0"] 了,触发stateQueue[0] = stateQueue[0] || initState;,这样就把 Tom 渲染到页面上了。
这是基本的渲染过程,将下来我们看看如果加到条件语句里面是怎么渲染的:
let show = false;
function RenderFunctionComponent() {if (show) {const [name, setName] = useState("Lvan");}const [age, setAge] = useState("0");return (<div>{name}</div><div>{age}</div><Button onClick={() => setName("Tom")}>name设置为Tom</Button>);
}
很明显,如果这里加上 if 判断,那么 render 的时候,这个 index 就不能一一对应上了。
那么有的同学就会问了,为什么要用这种设计,就不能换种设计方案,比如用一个参数来对应起来。比如说 const [name, setName] = useState("name", "Lvan");,这样就可以知道我是设置 name 这个字段了而不是找 index,这样做当然可以实现。
我觉得 react 没有这样做可能有几个原因:
- 这样更简洁
- 函数式开发
- 并发性能高
总结
所以为了回答题目的问题,我们可以说因为 hooks 内部使用链表来实现。
但是,并不是因为 hooks 内部使用链表来实现,所以我们必须保证 hooks 的调用顺序。这种观点显然倒置了因果关系。
正确的说法是:因为我们为了保证了 hooks 的调用顺序(不保证就会报错),所以 hooks 内部可以使用链表来实现。
参考资料
https://www.zhihu.com/question/532521785/answer/2490282912
相关文章:
react:hooks为什么不能写在条件语句里
背景 最近朋友在面试,说面试官问到了一个问题不会,说为什么 react hooks为什么不能写在条件语句里,今天我们来研究一下这个问题。 我们在来简单实现一个 useState: const reRender () > {stateIndex -1 ReactDOM.render(&…...
模型优势缺陷整理
(1)BERT 1. 计算资源消耗:bert模型是一个相对较大的模型,具有数亿个参数。因此,为了训练和使用bert模型,需要大量的计算资源和时间。 2. 学习不足问题:尽管bert模型在大规模语料库上进行了预训…...
编写猫咪相册应用 HTML
文章目录1. 标题元素标签2. p元素用于在网站上创建一段文本3. 注释4. 页面主要部分标识标签5. 通过使用img元素来为你的网站添加图片6. 使用锚点元素(a)链接到另一个页面7. 使用 section 元素将照片内容与未来的内容分开8. 无序列表(ul)元素,列表项(li)元素在列表中…...
基于Arduino与LabVIEW的远程家庭监控系统
在基于Arduino与LabVIEW的远程家庭监控系统中,Arduino Uno控制器需要完成以下功能:1)通过W5100网络模块接收并判断命令,采集和传输温度、煤气浓度、热释电传感器的数据,并通过W5100网络模块上传给LabVIEW软件。2&#…...
使用FRP(快速反向代理)实现内网穿透——以腾讯云服务器为例
一、FRP简介 FRP,即快速反向代理技术(fast reverse proxy)。本文的FRP程序是基于github开源项目GitHub - fatedier/frp。当前,该程序可实现:“将位于 NAT 或防火墙后面的本地服务器暴露给互联网”。它目前支持 TCP 和…...
d跨语言链接优化
原文 使用LDC的(LTO)链接时优化的简短文章,包含演示了如何提高程序性能的简单示例.因为LTO在LLVMIR级别工作,因此可跨越C/D语言优化! 重要提示:LDC/LLVM的LTO在窗口上不可用. 链接时优化 (LTO)链接时优化是指链接时的程序优化.链接器提取所有目标文件在一起,并合并到一个程序…...
【Linux】-- 进程概念的引入
目录 硬件 冯诺依曼体系结构 冯诺依曼体系结构推导 重点概念 网络数据流向 软件 操作系统(Operator System - OS) 概念 定位 进程内核数据结构PCB(task_struct) 通过系统调用创建进程-fork初始 fork基本用法 使用if进行分流 查看运行效果 …...
一文看懂“低代码、零代码”是什么?有什么区别?
低代码和零代码近几年热度一直居高不下,乍一看,很容易混淆低代码和零代码开发平台—— 因为它们都是传统开发的替代方案,旨在通过类似于可视化编程的功能加速软件开发过程。 但二者根本不是一回事。从开发人员经验 、目标角色到使用场景&…...
【华为OD机试真题】去除多余的空格(java)
去除多余空格 知识点字符串数组Q队列时间限制:2s空间限制:256MB限定语言:不限 题目描述: 去除文本多余空格,但不去除配对单引号之间的多余空格。给出关键词的起始和结束 下标,去除多余空格后刷新关键词的起始和结束下标。 输入: Life is painting a picture, not …...
【SQL 必知必会】- 第十三课 创建高级联结
目录 使用表别名 Oracle 中没有AS 使用不同类型的联结 自联结 用自联结而不用子查询 自然联结 外联结 全外联结 使用带聚集函数的联结 使用联结和联结条件 使用表别名 SQL 除了可以对列名和计算字段使用别名,还允许给表名起别名。这样做有两个主要理由ÿ…...
ios逆向工具有那些
以下是一些常用的 iOS 逆向工具: Cycript:一种用于在运行时动态分析和修改 iOS 应用程序的强大工具,可以与应用程序进行交互式调试和注入代码。 Frida:一个强大的动态二进制插桩工具,可以在运行时修改应用程序的行为&…...
【软件设计师14】UML建模
UML建模 稳定出一个,但是由于UML的图比较多,所以这种题比数据流图和数据库难度高 一般都会考用例图和类图,再附加其他的图 1. 用例图 包含关系include:比如登记外借信息必须先有用户登录 扩展关系extend:修改书籍…...
容器镜像的设计原理
1 概述: 1.1 历史概要 2016年,Docker制定了镜像规范v2,并在Docker 1.10中实现了这个规范。镜像规范v2分为Schema 1和Schema 2。 Schema 1主要兼容使用v1规范的Docker客户端(从2017年2月起,镜像规范v1不再被Registry支…...
arm64异常向量表
arm64异常向量表1 arm64异常向量表2 linux arm64异常向量表3 kernel_ventry宏4 异常向量表的保存4. VBAR_ELx寄存器4.2 __primary_switched4.3 __primary_switched1 arm64异常向量表 When an exception occurs, the processor must execute handler code which corresponds to …...
【测试面试】吐血整理,大厂测试开发岗面试题(1~4面),拿下年40w...
目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)前言 自动化测试面试题&am…...
SpringSecurity之权限模块设计
目录 前言 实现思路 代码结构 使用说明 前言 前面我们了解了关于微服务权限设计方案以及J W T的相关介绍,今天我们来聊一下,如何避免自己重复的写相同的代码,一次代码实现,即可完美复制到任何项目中实现权限相关的功能。 实现…...
002_双指针法
1.移除元素 目标:移除数组中的某一个元素 数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。 1.1暴力解法 建立两个for循环,当查找到某个元素以后,将此元素后面的元素全部往前移动 时间复…...
超实用的 Linux 高级命令,程序员一定要懂
前言 在运维的坑里摸爬滚打好几年了,我还记得我刚开始的时候,我只会使用一些简单的命令,写脚本的时候,也是要多简单有多简单,所以有时候写出来的脚本又长又臭。 像一些高级点的命令,比如说 Xargs 命令、管…...
AI+明厨亮灶智能算法 yolo
AI明厨亮灶智能算法通过pythonyolo网络模型分析算法,AI明厨亮灶模型算法可接对后厨实现如口罩识别、厨师服穿戴、夜间老鼠监测、厨师帽识别、厨师玩手机打电话识别、抽烟识别等实时分析监测。Python是一种由Guido van Rossum开发的通用编程语言,它很快就…...
gRPC-Go源码解读一 客户端请求链路分析
最近在学习gRPC相关的知识,为啥要学呢?因为一直在用,古人云,“工欲善其事,必先利其器”。为此,花了不少时间阅读gRPC-Go的源码,收货甚多,比如透过服务发现和负载均衡这俩组件来学习复…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
k8s从入门到放弃之HPA控制器
k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率(或其他自定义指标)来调整这些对象的规模,从而帮助应用程序在负…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...
微服务通信安全:深入解析mTLS的原理与实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言:微服务时代的通信安全挑战 随着云原生和微服务架构的普及,服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...
医疗AI模型可解释性编程研究:基于SHAP、LIME与Anchor
1 医疗树模型与可解释人工智能基础 医疗领域的人工智能应用正迅速从理论研究转向临床实践,在这一过程中,模型可解释性已成为确保AI系统被医疗专业人员接受和信任的关键因素。基于树模型的集成算法(如RandomForest、XGBoost、LightGBM)因其卓越的预测性能和相对良好的解释性…...
Python爬虫(四):PyQuery 框架
PyQuery 框架详解与对比 BeautifulSoup 第一部分:PyQuery 框架介绍 1. PyQuery 是什么? PyQuery 是一个 Python 的 HTML/XML 解析库,它采用了 jQuery 的语法风格,让开发者能够用类似前端 jQuery 的方式处理文档解析。它的核心特…...
