为什么React的Hooks不能在条件语句和循环语句中使用?
道理非常简单。
假设 React 允许 useState 处于条件语句中,那么我们从 React 的视角来看看会发生什么。
假设第一次 render 的 useState 情况如下:
此时用户触发 setNextB(b+1) 于是有了第二次 render。
假设第二次 render 的 useState 情况如下:
const [b, setNextB] = useState(0)
即,由于某种原因,你少调用了一次 useState。
请问,此时 b 等于多少?你会说 b 加 1 了呀,当然变成 1 了,但是 React 怎么会知道这些?
React 只知道
1. 第一次 render 时 useState 被调用了 2 次,记为调用 1 和调用 2
2. 调用 2 返回的数组的第二项被调用了,即 setNextB(b+1),触发第二次 render
3. 第二次 render 时 useState 被调用了 1 次,记为调用 3
请问,调用 3 返回的结果是要跟调用 1 相关还是要跟调用 2 相关?
答案是:React 不知道。
因为从 React 角度来看,根本就看不见变量 a 和变量 b!React 只知道 useState 的返回值被你拿去了,但是你拿去之后赋值给什么变量,React 根本就不知道。
如果你一定想让 React 识别 a 和 b,那么可以用下面假想的 useState 把 a 和 b 传给 React:
const [a, setNextA] = useState('a', 0) // 这种 useState 是不存在的
const [b, setNextB] = useState('b', 0)
加上 key 之后,后续的 render 就能匹配上 a 和 b 了。
因为你的第二次 render 是这样的:
const [b, setNextB] = useState('b', 0)
React 当然就会知道这是 b 不是 a。
相信你已经发现问题所在了,React 不允许 hook 处于条件语句是因为 React 把每次 render 中 useState 的顺序值 0、1、2、3 当成了 key,方便后续 render 用 key 查找对应的 state。这样的目的是使 useState 更简洁。(不止 useState,其他 hook 也不允许处于条件语句中)
当然,React 这么做的目的也可能是为了追求函数式或者并发,但显然大部分前端开发者并不在乎这些。
注意,并不是因为 hooks 内部使用链表来实现,所以我们必须保证 hooks 的调用顺序。这种观点显然倒置了因果关系,正确的说法是:因为我们保证了 hooks 的调用顺序(不保证就会报错),所以 hooks 内部可以使用链表来实现。
相关推荐HOT
更多>>xml解析器
SAX解析器:基于事件驱动的解析器,逐行读取XML文件并触发相应的事件,适用于处理大型XML文件,但需要手动编写事件处理器来处理XML文件中的数据...详情>>
2023-03-21 16:03:51java全局变量
如果全局变量是一个对象,则可以更改该对象的状态,即使变量本身是final类型。当一个方法被调用时,会为该方法在栈上分配一块内存空间,用于存...详情>>
2023-03-17 10:01:40带你手把手解决Java常见Bug
刚开始学习Java语言的小伙伴, 很可能被各种各样的程序bug搞得焦头烂额, 甚至被劝退。别怕,小编将手把手带你了解Java中的异常体系, 如何识别Bug...详情>>
2023-03-13 16:05:00JavaScript 内的 this 指向
在 javascript 语言中, 有一个奇奇怪怪的 "关键字" 叫做 this详情>>
2023-03-07 15:21:00