-
Notifications
You must be signed in to change notification settings - Fork 546
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
React Hooks 原理 #26
Comments
为什么 state声明在外面,点击的时候,view才变化,没想明白 @brickspert |
@liang520 如果放在 useState 里面,是不是重新渲染每次都会重新调用 useState 重置掉? |
@brickspert 看明白了 |
memoizedState => memorizedState |
砖家写的文章依旧简单明了~ |
很清晰明了了 |
除了用变量存state还有别的吗 |
当我以为我会用hook的时候 useEffect 内的 setInterval 把我打蒙了,闭包是啥时候出现的都没看懂 |
一直关注,一直学习,感谢你的陪伴,可以借鉴学习React Hooks 入门教程http://www.ruanyifeng.com/blog/2019/09/react-hooks.html |
follow |
赞,会用与会实现,理解的深度就是不一样 |
不然的话state只是一个useState函数里边的局部变量,每次执行都会重新初始化为0呀 |
是否需要在setState函数中把cursor重置为0,在rerender的时候才能按照hook在组件函数内的书写顺序从0依次获取memoizedState中的值? function setState(newState) {
memoizedState[currentCursor] = newState;
// reset
cursor = 0;
render();
} |
例子中在 render() 里面把 cursor 置为 0 了。 |
为什么是 1 呢?每次都是从 0 开始重新执行的。可以在这个例子中试试呢: |
请问,这个useState在多个组件中引入,彼此之间会不会有影响(全局只有一个memoizedState )? |
这个例子里面会。因为共用了一个 memoizedState。 |
@brickspert 多谢多谢 |
棒! |
感谢~,已修正。 |
我看你代码是 render 的时候才修改 cursor 为 0 吧,事件触发的时候,当时的 currentCursor 是 1,这时就会改变 memorizState[1] 的值 |
这句话我不能理解,博主能引用源代码来证明么? |
还有建议:给 useState 里的 render() 那块加个注释,我刚开始看这块的时候,也比较懵 |
最近面试遇到这个问题,大致了解了一下,链表是在内存里申请了一块连续的空间,而map是随机分散存储的,所以链表的查询会更快一些,一般大佬们的程序都会考虑要结合硬件层面来设计的 |
受教了 |
链表是动态分配内存,是非连续的。数组才是连续的,且是静态分配的 |
貌似JS底层的数组也有分快数组和慢数组,慢数组用的是hash表来管理数组,也就是说其数组的内存应该不是连续的? |
应该是使用key value 会有key冲突的问题需要解决吧 |
··· function useEffect(callback, depArray) { |
空数组的话,!depArray 应该是 false 呀。 |
厉害,学习了 |
佩服!看了很多个讲解 hooks 原理的,讲得这么清晰易懂的就是🧱家这 |
写在里面函数每次执行都会重置 |
就是要 false 呀 |
全量 rerender 确实不会影响到 hooks 游标 index; 更新(2021-10-15): 可能是实现上每个组件都绑定一个hooks数组,只需要在每个组件运行的时候维护一个独立游标即可,所以不存在全局的hookIndex紊乱问题 更新(2021-12-3): 依照上面的思路实现了一个简单版本的Hooks(可以局部更新) |
有毛病,如果我把state变成undefined,null,0, false这些的时候就会重置成initialState |
确实 其实 |
没毛病,immutable模式 |
一个组件内,react 是如何抓区和解析多个 useEffect 的 |
可以理解成每个组件内都会关联一个hooks队列 |
请问能讲下这块的工作原理吗 |
楼主讲的算比较清楚了,具体实现可以看源码,啃不动的可以试试看这个简单的实现 |
对这里不是很理解 困惑点在于:虽然每一次都会进行ReRender,但是如果都会从同一个memoizedState中取值的话,应该是能够获取到最新的值,不会存在“Capture Value” 特性 拜托大佬解惑~ |
因为每次重新render 的时候会重新执行 useState(0)呀,如果不放在外面的话,返回的state还是0 |
想问一下,我记得js的数组并不需要连续空间吧? |
前言
目前,Hooks 应该是 React 中最火的概念了,在阅读这篇文章之前,希望你已经了解了基本的 Hooks 用法。
在使用 Hooks 的时候,我们可能会有很多疑惑
这篇文章我们不会讲解 Hooks 的概念和用法,而是会带你从零实现一个 tiny hooks,知其然知其所以然。
useState
最简单的 useState 用法是这样的:
demo1: https://codesandbox.io/s/v0nqm309q3
基于 useState 的用法,我们尝试着自己实现一个 useState:
demo2:https://codesandbox.io/s/myy5qvoxpp
这时我们发现,点击 Button 的时候,count 并不会变化,为什么呢?我们没有存储 state,每次渲染 Counter 组件的时候,state 都是新重置的。
自然我们就能想到,把 state 提取出来,存在 useState 外面。
demo3:https://codesandbox.io/s/q9wq6w5k3w
到目前为止,我们实现了一个可以工作的 useState,至少现在来看没啥问题。
接下来,让我们看看 useEffect 是怎么实现的。
useEffect
useEffect 是另外一个基础的 Hook,用来处理副作用,最简单的用法是这样的:
demo4:https://codesandbox.io/s/93jp55qyp4
我们知道 useEffect 有几个特点:
我们来实现一个 useEffect
demo5:https://codesandbox.io/s/3kv3zlvzl1
到这里,我们又实现了一个可以工作的 useEffect,似乎没有那么难。
此时我们应该可以解答一个问题:
Q:为什么第二个参数是空数组,相当于
componentDidMount
?A:因为依赖一直不变化,callback 不会二次执行。
Not Magic, just Arrays
到现在为止,我们已经实现了可以工作的 useState 和 useEffect。但是有一个很大的问题:它俩都只能使用一次,因为只有一个 _state 和 一个 _deps。比如
count 和 username 永远是相等的,因为他们共用了一个 _state,并没有地方能分别存储两个值。我们需要可以存储多个 _state 和 _deps。
如 《React hooks: not magic, just arrays》所写,我们可以使用数组,来解决 Hooks 的复用问题。
demo6:https://codesandbox.io/s/50ww35vkzl
代码关键在于:
我们用图来描述 memoizedState 及 cursor 变化的过程。
1. 初始化

2. 初次渲染
3. 事件触发
4. Re Render
到这里,我们实现了一个可以任意复用的 useState 和 useEffect。
同时,也可以解答几个问题:
Q:为什么只能在函数最外层调用 Hook?为什么不要在循环、条件判断或者子函数中调用。
A:memoizedState 数组是按 hook定义的顺序来放置数据的,如果 hook 顺序变化,memoizedState 并不会感知到。
Q:自定义的 Hook 是如何影响使用它的函数组件的?
A:共享同一个 memoizedState,共享同一个顺序。
Q:“Capture Value” 特性是如何产生的?
A:每一次 ReRender 的时候,都是重新去执行函数组件了,对于之前已经执行过的函数组件,并不会做任何操作。
真正的 React 实现
虽然我们用数组基本实现了一个可用的 Hooks,了解了 Hooks 的原理,但在 React 中,实现方式却有一些差异的。
React 中是通过类似单链表的形式来代替数组的。通过 next 按顺序串联所有的 hook。
memoizedState,cursor 是存在哪里的?如何和每个函数组件一一对应的?
我们知道,react 会生成一棵组件树(或Fiber 单链表),树中每个节点对应了一个组件,hooks 的数据就作为组件的一个信息,存储在这些节点上,伴随组件一起出生,一起死亡。
参考文章
❤️感谢大家
关注公众号「前端技术砖家」,拉你进交流群,大家一起共同交流和进步。
The text was updated successfully, but these errors were encountered: