当前位置: 首页 > 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

http://www.lryc.cn/news/59454.html

相关文章:

  • 模型优势缺陷整理
  • 编写猫咪相册应用 HTML
  • 基于Arduino与LabVIEW的远程家庭监控系统
  • 使用FRP(快速反向代理)实现内网穿透——以腾讯云服务器为例
  • d跨语言链接优化
  • 【Linux】-- 进程概念的引入
  • 一文看懂“低代码、零代码”是什么?有什么区别?
  • 【华为OD机试真题】去除多余的空格(java)
  • 【SQL 必知必会】- 第十三课 创建高级联结
  • ios逆向工具有那些
  • 【软件设计师14】UML建模
  • 容器镜像的设计原理
  • arm64异常向量表
  • 【测试面试】吐血整理,大厂测试开发岗面试题(1~4面),拿下年40w...
  • SpringSecurity之权限模块设计
  • 002_双指针法
  • 超实用的 Linux 高级命令,程序员一定要懂
  • AI+明厨亮灶智能算法 yolo
  • gRPC-Go源码解读一 客户端请求链路分析
  • Word控件Spire.Doc for .net 功能详解
  • 联想服务器配置RAID
  • C++ 虚函数表
  • rancher2.7丢失集群信息
  • 数据库管理-第六十八期 Oracle 23c的其他(20230417)
  • 精准关键词获取-行业搜索词分析
  • c++学习之c++对c的扩展1
  • Redis锁的租约问题
  • 2023年全国最新高校辅导员精选真题及答案50
  • mall商城之k8s部署-4
  • 使用Go语言打造轻量级Web框架