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

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为什么不能写在条件语句里

背景 最近朋友在面试&#xff0c;说面试官问到了一个问题不会&#xff0c;说为什么 react hooks为什么不能写在条件语句里&#xff0c;今天我们来研究一下这个问题。 我们在来简单实现一个 useState&#xff1a; const reRender () > {stateIndex -1 ReactDOM.render(&…...

模型优势缺陷整理

&#xff08;1&#xff09;BERT 1. 计算资源消耗&#xff1a;bert模型是一个相对较大的模型&#xff0c;具有数亿个参数。因此&#xff0c;为了训练和使用bert模型&#xff0c;需要大量的计算资源和时间。 2. 学习不足问题&#xff1a;尽管bert模型在大规模语料库上进行了预训…...

编写猫咪相册应用 HTML

文章目录1. 标题元素标签2. p元素用于在网站上创建一段文本3. 注释4. 页面主要部分标识标签5. 通过使用img元素来为你的网站添加图片6. 使用锚点元素(a)链接到另一个页面7. 使用 section 元素将照片内容与未来的内容分开8. 无序列表(ul)元素&#xff0c;列表项(li)元素在列表中…...

基于Arduino与LabVIEW的远程家庭监控系统

在基于Arduino与LabVIEW的远程家庭监控系统中&#xff0c;Arduino Uno控制器需要完成以下功能&#xff1a;1&#xff09;通过W5100网络模块接收并判断命令&#xff0c;采集和传输温度、煤气浓度、热释电传感器的数据&#xff0c;并通过W5100网络模块上传给LabVIEW软件。2&#…...

使用FRP(快速反向代理)实现内网穿透——以腾讯云服务器为例

一、FRP简介 FRP&#xff0c;即快速反向代理技术&#xff08;fast reverse proxy&#xff09;。本文的FRP程序是基于github开源项目GitHub - fatedier/frp。当前&#xff0c;该程序可实现&#xff1a;“将位于 NAT 或防火墙后面的本地服务器暴露给互联网”。它目前支持 TCP 和…...

d跨语言链接优化

原文 使用LDC的(LTO)链接时优化的简短文章,包含演示了如何提高程序性能的简单示例.因为LTO在LLVMIR级别工作,因此可跨越C/D语言优化! 重要提示:LDC/LLVM的LTO在窗口上不可用. 链接时优化 (LTO)链接时优化是指链接时的程序优化.链接器提取所有目标文件在一起,并合并到一个程序…...

【Linux】-- 进程概念的引入

目录 硬件 冯诺依曼体系结构 冯诺依曼体系结构推导 重点概念 网络数据流向 软件 操作系统(Operator System - OS) 概念 定位 进程内核数据结构PCB&#xff08;task_struct&#xff09; 通过系统调用创建进程-fork初始 fork基本用法 使用if进行分流 查看运行效果 …...

一文看懂“低代码、零代码”是什么?有什么区别?

低代码和零代码近几年热度一直居高不下&#xff0c;乍一看&#xff0c;很容易混淆低代码和零代码开发平台—— 因为它们都是传统开发的替代方案&#xff0c;旨在通过类似于可视化编程的功能加速软件开发过程。 但二者根本不是一回事。从开发人员经验 、目标角色到使用场景&…...

【华为OD机试真题】去除多余的空格(java)

去除多余空格 知识点字符串数组Q队列时间限制:2s空间限制:256MB限定语言:不限 题目描述: 去除文本多余空格,但不去除配对单引号之间的多余空格。给出关键词的起始和结束 下标,去除多余空格后刷新关键词的起始和结束下标。 输入: Life is painting a picture, not …...

【SQL 必知必会】- 第十三课 创建高级联结

目录 使用表别名 Oracle 中没有AS 使用不同类型的联结 自联结 用自联结而不用子查询 自然联结 外联结 全外联结 使用带聚集函数的联结 使用联结和联结条件 使用表别名 SQL 除了可以对列名和计算字段使用别名&#xff0c;还允许给表名起别名。这样做有两个主要理由&#xff…...

ios逆向工具有那些

以下是一些常用的 iOS 逆向工具&#xff1a; Cycript&#xff1a;一种用于在运行时动态分析和修改 iOS 应用程序的强大工具&#xff0c;可以与应用程序进行交互式调试和注入代码。 Frida&#xff1a;一个强大的动态二进制插桩工具&#xff0c;可以在运行时修改应用程序的行为&…...

【软件设计师14】UML建模

UML建模 稳定出一个&#xff0c;但是由于UML的图比较多&#xff0c;所以这种题比数据流图和数据库难度高 一般都会考用例图和类图&#xff0c;再附加其他的图 1. 用例图 包含关系include&#xff1a;比如登记外借信息必须先有用户登录 扩展关系extend&#xff1a;修改书籍…...

容器镜像的设计原理

1 概述&#xff1a; 1.1 历史概要 2016年&#xff0c;Docker制定了镜像规范v2&#xff0c;并在Docker 1.10中实现了这个规范。镜像规范v2分为Schema 1和Schema 2。 Schema 1主要兼容使用v1规范的Docker客户端&#xff08;从2017年2月起&#xff0c;镜像规范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...

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 自动化测试面试题&am…...

SpringSecurity之权限模块设计

目录 前言 实现思路 代码结构 使用说明 前言 前面我们了解了关于微服务权限设计方案以及J W T的相关介绍&#xff0c;今天我们来聊一下&#xff0c;如何避免自己重复的写相同的代码&#xff0c;一次代码实现&#xff0c;即可完美复制到任何项目中实现权限相关的功能。 实现…...

002_双指针法

1.移除元素 目标&#xff1a;移除数组中的某一个元素 数组的元素在内存地址中是连续的&#xff0c;不能单独删除数组中的某个元素&#xff0c;只能覆盖。 1.1暴力解法 建立两个for循环&#xff0c;当查找到某个元素以后&#xff0c;将此元素后面的元素全部往前移动 时间复…...

超实用的 Linux 高级命令,程序员一定要懂

前言 在运维的坑里摸爬滚打好几年了&#xff0c;我还记得我刚开始的时候&#xff0c;我只会使用一些简单的命令&#xff0c;写脚本的时候&#xff0c;也是要多简单有多简单&#xff0c;所以有时候写出来的脚本又长又臭。 像一些高级点的命令&#xff0c;比如说 Xargs 命令、管…...

AI+明厨亮灶智能算法 yolo

AI明厨亮灶智能算法通过pythonyolo网络模型分析算法&#xff0c;AI明厨亮灶模型算法可接对后厨实现如口罩识别、厨师服穿戴、夜间老鼠监测、厨师帽识别、厨师玩手机打电话识别、抽烟识别等实时分析监测。Python是一种由Guido van Rossum开发的通用编程语言&#xff0c;它很快就…...

gRPC-Go源码解读一 客户端请求链路分析

最近在学习gRPC相关的知识&#xff0c;为啥要学呢&#xff1f;因为一直在用&#xff0c;古人云&#xff0c;“工欲善其事&#xff0c;必先利其器”。为此&#xff0c;花了不少时间阅读gRPC-Go的源码&#xff0c;收货甚多&#xff0c;比如透过服务发现和负载均衡这俩组件来学习复…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

push [特殊字符] present

push &#x1f19a; present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中&#xff0c;push 和 present 是两种不同的视图控制器切换方式&#xff0c;它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...