Comments (68)
是否需要在setState函数中把cursor重置为0,在rerender的时候才能按照hook在组件函数内的书写顺序从0依次获取memoizedState中的值?
function setState(newState) { memoizedState[currentCursor] = newState; // reset cursor = 0; render(); }
例子中在 render() 里面把 cursor 置为 0 了。
from blog.
最开始有个疑问:为什么 useState 的 memoizedState 要是数组?如果是对象多好,这样就能一一对应上了,就可以突破 hooks 只能写在函数组件顶层的限制了。
看到最后,发现其实是个链表,并不是简单的数组呀。。。 所以我猜测为什么 memoizedState 不用 key value 这种方式存的原因是出于性能考虑吗?(也就是 key value 形式的数据结构 并没有 链表 形式的快)最近面试遇到这个问题,大致了解了一下,链表是在内存里申请了一块连续的空间,而map是随机分散存储的,所以链表的查询会更快一些,一般大佬们的程序都会考虑要结合硬件层面来设计的
链表是动态分配内存,是非连续的。数组才是连续的,且是静态分配的
from blog.
还是无法理解: “Capture Value” 特性是如何产生的
每次rerender都会重新执行一遍函数组件本身, 每次执行都会是全新的context,capture只是闭包保存对应的context,所以后续更新 不会影响之前的context,那之前闭包捕获的context也就不会变了。
from blog.
为什么 state声明在外面,点击的时候,view才变化,没想明白 @brickspert
from blog.
赞,会用与会实现,理解的深度就是不一样
from blog.
大神 有一点想请教一下
function useState(initialValue) {
memoizedState[cursor] = memoizedState[cursor] || initialValue;
const currentCursor = cursor;
function setState(newState) {
memoizedState[currentCursor] = newState;
render();
}
return [memoizedState[cursor++], setState]; // 返回当前 state,并把 cursor 加 1
}
对于memoizedState[cursor] = memoizedState[cursor] || initialValue;这么实现的话 是不是如果setState(null)或者是setState(undefind)是不是 state都会被付成默认值了
from blog.
为什么是 1 呢?每次都是从 0 开始重新执行的。可以在这个例子中试试呢:
https://codesandbox.io/s/50ww35vkzl
这里从0开始,是指render都会从0开始执行hook。但是对于setUsername('fan hello')这个setState方法来说,cursor应该是1。
这是我个人的理解,这个图上标注似乎会引起一点歧义,如果不对请指正
from blog.
为什么是 1 呢?每次都是从 0 开始重新执行的。可以在这个例子中试试呢:
https://codesandbox.io/s/50ww35vkzl这里从0开始,是指render都会从0开始执行hook。但是对于setUsername('fan hello')这个setState方法来说,cursor应该是1。
这是我个人的理解,这个图上标注似乎会引起一点歧义,如果不对请指正
第一句描述的没有异议,第二句中的 "cursor 应该是 1" 这句存在歧义,我们可以观察一下 setState 方法执行过程,发现其中维护memoizedState 数组下标的变量是 useState 方法中定义的 currentCursor 变量而不是 cursor,实际上 currentCursor 的值才是1。变量 cursor 的值在执行setState 中 render 方法之前是 memoizedState 数组的长度(即所存储hooks的数量,因为 useState 和 useEffect 中最后都执行了cursor++ 操作),在执行setState 中 render方法之后才会重置为 0。
图中描述的是变量 cursor 值的变化,所以作者描述的没什么问题,如果加上 currentCursor 值得变化大家可能就更容易理解了。
from blog.
请问,这个useState在多个组件中引入,彼此之间会不会有影响(全局只有一个memoizedState )?
这个例子里面会。因为共用了一个 memoizedState。
但是在 React 中,是把数据存在 fiber node 上的。也就是,每个组件都有自己的 memoizedState.
from blog.
棒!
_state = _state | initialValue
应该是_state = _state || initialValue
感谢~,已修正。
from blog.
@liang520 如果放在 useState 里面,是不是重新渲染每次都会重新调用 useState 重置掉?
from blog.
@brickspert 看明白了
from blog.
memoizedState => memorizedState
from blog.
砖家写的文章依旧简单明了~
from blog.
很清晰明了了
from blog.
除了用变量存state还有别的吗
from blog.
当我以为我会用hook的时候 useEffect 内的 setInterval 把我打蒙了,闭包是啥时候出现的都没看懂
from blog.
一直关注,一直学习,感谢你的陪伴,可以借鉴学习React Hooks 入门教程http://www.ruanyifeng.com/blog/2019/09/react-hooks.html
from blog.
follow
from blog.
为什么 state声明在外面,点击的时候,view才变化,没想明白 @brickspert
不然的话state只是一个useState函数里边的局部变量,每次执行都会重新初始化为0呀
from blog.
是否需要在setState函数中把cursor重置为0,在rerender的时候才能按照hook在组件函数内的书写顺序从0依次获取memoizedState中的值?
function setState(newState) {
memoizedState[currentCursor] = newState;
// reset
cursor = 0;
render();
}
from blog.
from blog.
我也觉得此时的cursor不应该为0,为1的是currentCursor 这个局部变量,用来获取userName这个state在数组中的位置
from blog.
我也觉得此时的cursor不应该为0,为1的是currentCursor 这个局部变量,用来获取userName这个state在数组中的位置
同意。随处可见的闭包啊~
from blog.
为什么是 1 呢?每次都是从 0 开始重新执行的。可以在这个例子中试试呢:
https://codesandbox.io/s/50ww35vkzl
from blog.
请问,这个useState在多个组件中引入,彼此之间会不会有影响(全局只有一个memoizedState )?
from blog.
@brickspert 多谢多谢
from blog.
棒! _state = _state | initialValue
应该是 _state = _state || initialValue
from blog.
为什么是 1 呢?每次都是从 0 开始重新执行的。可以在这个例子中试试呢:
https://codesandbox.io/s/50ww35vkzl
我看你代码是 render 的时候才修改 cursor 为 0 吧,事件触发的时候,当时的 currentCursor 是 1,这时就会改变 memorizState[1] 的值
from blog.
memoizedState,cursor 是存在哪里的?如何和每个函数组件一一对应的?
我们知道,react 会生成一棵组件树(或Fiber 单链表),树中每个节点对应了一个组件,hooks 的数据就作为组件的一个信息,存储在这些节点上,伴随组件一起出生,一起死亡。
这句话我不能理解,博主能引用源代码来证明么?
就我理解,函数式组件既然已经是stateless,就不会有所谓出生,死亡等生命周期了。我更倾向于react的hook信息,即整个hook的链表是一个全局变量。
from blog.
memoizedState,cursor 是存在哪里的?如何和每个函数组件一一对应的? 我们知道,react 会生成一棵组件树(或Fiber 单链表),树中每个节点对应了一个组件,hooks 的数据就作为组件的一个信息,存储在这些节点上,伴随组件一起出生,一起死亡。
这句话我不能理解,博主能引用源代码来证明么?
就我理解,函数式组件既然已经是stateless,就不会有所谓出生,死亡等生命周期了。我更倾向于react的hook信息,即整个hook的链表是一个全局变量。
收回我的猜想。全局的hook无法实现条件渲染,应该是每个组件对应各自的hook。
from blog.
还是无法理解: “Capture Value” 特性是如何产生的
from blog.
理解了, 每次render 就是一个闭包, 会缓存住当前的所有状态, react class 是直接更新this.props的指向, 且没有闭包的概念, 所以全变了
from blog.
在demo3中,没有调用诸如useState或者this.setState之类的方法,那react是如何知道并且触发更新的呢?
from blog.
在demo3中,没有调用诸如useState或者this.setState之类的方法,那react是如何知道并且触发更新的呢?
抱歉,忽略了里面的render方法
from blog.
function setState(newState) {
memoizedState[currentCursor] = newState;
cursor = currentCursor; //是不是少了这一句??
render();
}
from blog.
function setState(newState) { memoizedState[currentCursor] = newState; cursor = currentCursor; //是不是少了这一句?? render(); }
不需要吧
下一步render()就會把cursor = 0
並且再次依照順序調用所有函數組件
from blog.
大神 有一点想请教一下
function useState(initialValue) {
memoizedState[cursor] = memoizedState[cursor] || initialValue;
const currentCursor = cursor;
function setState(newState) {
memoizedState[currentCursor] = newState;
render();
}
return [memoizedState[cursor++], setState]; // 返回当前 state,并把 cursor 加 1
}
对于memoizedState[cursor] = memoizedState[cursor] || initialValue;这么实现的话 是不是如果setState(null)或者是setState(undefind)是不是 state都会被付成默认值了
我也是有这么个疑问,如果值本身就是false的话,怎么办?
from blog.
大神 有一点想请教一下
function useState(initialValue) {
memoizedState[cursor] = memoizedState[cursor] || initialValue;
const currentCursor = cursor;
function setState(newState) {
memoizedState[currentCursor] = newState;
render();
}
return [memoizedState[cursor++], setState]; // 返回当前 state,并把 cursor 加 1
}
对于memoizedState[cursor] = memoizedState[cursor] || initialValue;这么实现的话 是不是如果setState(null)或者是setState(undefind)是不是 state都会被付成默认值了
确实会有这个问题。
这个文章只是一个示例 demo,不是百分百严谨。
from blog.
大神 有一点想请教一下
function useState(initialValue) {
memoizedState[cursor] = memoizedState[cursor] || initialValue;
const currentCursor = cursor;
function setState(newState) {
memoizedState[currentCursor] = newState;
render();
}
return [memoizedState[cursor++], setState]; // 返回当前 state,并把 cursor 加 1
}
对于memoizedState[cursor] = memoizedState[cursor] || initialValue;这么实现的话 是不是如果setState(null)或者是setState(undefind)是不是 state都会被付成默认值了确实会有这个问题。
这个文章只是一个示例 demo,不是百分百严谨。
明白啦!还是感谢作者带来质量那么高的文章。
from blog.
看了好久那里没想明白cursor怎么重置为0的,看了demo才知道,哭了。
from blog.
🧱家就是强 通俗易懂 顺便问个问题 React为何要使用链表串联多个hook 相比数组的优势是什么呢?
from blog.
🧱家就是强 通俗易懂 顺便问个问题 React为何要使用链表串联多个hook 相比数组的优势是什么呢?
感觉链表的灵活性会比数组来的高吧?
from blog.
🧱家就是强 通俗易懂 顺便问个问题 React为何要使用链表串联多个hook 相比数组的优势是什么呢?
数组存储区间需要连续的内存,链表是则是非连续、非顺序的存储结构
from blog.
不懂就问,render函数怎么来的,是如何触发函数组件跟新的呢?
from blog.
不懂就问,render函数怎么来的,是如何触发函数组件跟新的呢?
看 demo 代码,有定义 render 函数
from blog.
最开始有个疑问:为什么 useState 的 memoizedState 要是数组?如果是对象多好,这样就能一一对应上了,就可以突破 hooks 只能写在函数组件顶层的限制了。
看到最后,发现其实是个链表,并不是简单的数组呀。。。 所以我猜测为什么 memoizedState 不用 key value 这种方式存的原因是出于性能考虑吗?(也就是 key value 形式的数据结构 并没有 链表 形式的快)
from blog.
还有建议:给 useState 里的 render() 那块加个注释,我刚开始看这块的时候,也比较懵
from blog.
最开始有个疑问:为什么 useState 的 memoizedState 要是数组?如果是对象多好,这样就能一一对应上了,就可以突破 hooks 只能写在函数组件顶层的限制了。
看到最后,发现其实是个链表,并不是简单的数组呀。。。 所以我猜测为什么 memoizedState 不用 key value 这种方式存的原因是出于性能考虑吗?(也就是 key value 形式的数据结构 并没有 链表 形式的快)
最近面试遇到这个问题,大致了解了一下,链表是在内存里申请了一块连续的空间,而map是随机分散存储的,所以链表的查询会更快一些,一般大佬们的程序都会考虑要结合硬件层面来设计的
from blog.
受教了
from blog.
最开始有个疑问:为什么 useState 的 memoizedState 要是数组?如果是对象多好,这样就能一一对应上了,就可以突破 hooks 只能写在函数组件顶层的限制了。
看到最后,发现其实是个链表,并不是简单的数组呀。。。 所以我猜测为什么 memoizedState 不用 key value 这种方式存的原因是出于性能考虑吗?(也就是 key value 形式的数据结构 并没有 链表 形式的快)最近面试遇到这个问题,大致了解了一下,链表是在内存里申请了一块连续的空间,而map是随机分散存储的,所以链表的查询会更快一些,一般大佬们的程序都会考虑要结合硬件层面来设计的
链表是动态分配内存,是非连续的。数组才是连续的,且是静态分配的
貌似JS底层的数组也有分快数组和慢数组,慢数组用的是hash表来管理数组,也就是说其数组的内存应该不是连续的?
from blog.
最开始有个疑问:为什么 useState 的 memoizedState 要是数组?如果是对象多好,这样就能一一对应上了,就可以突破 hooks 只能写在函数组件顶层的限制了。
看到最后,发现其实是个链表,并不是简单的数组呀。。。 所以我猜测为什么 memoizedState 不用 key value 这种方式存的原因是出于性能考虑吗?(也就是 key value 形式的数据结构 并没有 链表 形式的快)最近面试遇到这个问题,大致了解了一下,链表是在内存里申请了一块连续的空间,而map是随机分散存储的,所以链表的查询会更快一些,一般大佬们的程序都会考虑要结合硬件层面来设计的
链表是动态分配内存,是非连续的。数组才是连续的,且是静态分配的
应该是使用key value 会有key冲突的问题需要解决吧
from blog.
···
let _deps; // _deps 记录 useEffect 上一次的 依赖
function useEffect(callback, depArray) {
const hasNoDeps = !depArray; // 如果 dependencies 不存在
const hasChangedDeps = _deps
? !depArray.every((el, i) => el === _deps[i]) // 两次的 dependencies 是否完全相等
: true;
/* 如果 dependencies 不存在,或者 dependencies 有变化*/
if (hasNoDeps || hasChangedDeps) {
callback();
_deps = depArray;
}
}
···
depArray为空数组的时候,const hasNoDeps = !depArray;的值不一直是true,那么每次都callback都会执行吗?
from blog.
···
let _deps; // _deps 记录 useEffect 上一次的 依赖function useEffect(callback, depArray) {
const hasNoDeps = !depArray; // 如果 dependencies 不存在
const hasChangedDeps = _deps
? !depArray.every((el, i) => el === _deps[i]) // 两次的 dependencies 是否完全相等
: true;
/* 如果 dependencies 不存在,或者 dependencies 有变化*/
if (hasNoDeps || hasChangedDeps) {
callback();
_deps = depArray;
}
}
···
depArray为空数组的时候,const hasNoDeps = !depArray;的值不一直是true,那么每次都callback都会执行吗?
空数组的话,!depArray 应该是 false 呀。
from blog.
厉害,学习了
from blog.
佩服!看了很多个讲解 hooks 原理的,讲得这么清晰易懂的就是🧱家这
from blog.
为什么 state声明在外面,点击的时候,view才变化,没想明白 @brickspert
写在里面函数每次执行都会重置
from blog.
···
let _deps; // _deps 记录 useEffect 上一次的 依赖
function useEffect(callback, depArray) {
const hasNoDeps = !depArray; // 如果 dependencies 不存在
const hasChangedDeps = _deps
? !depArray.every((el, i) => el === _deps[i]) // 两次的 dependencies 是否完全相等
: true;
/* 如果 dependencies 不存在,或者 dependencies 有变化*/
if (hasNoDeps || hasChangedDeps) {
callback();
_deps = depArray;
}
}
···
depArray为空数组的时候,const hasNoDeps = !depArray;的值不一直是true,那么每次都callback都会执行吗?空数组的话,!depArray 应该是 false 呀。
就是要 false 呀
from blog.
全量 rerender 确实不会影响到 hooks 游标 index;
局部update如何确保index对应关系 (我理解这里只触发了部分hooks的,那游标是不是错乱了)?
还是在全量render的时候就跟vnode绑定,到更新的时候再动态重置游标?
更新(2021-10-15):
可能是实现上每个组件都绑定一个hooks数组,只需要在每个组件运行的时候维护一个独立游标即可,所以不存在全局的hookIndex紊乱问题
更新(2021-12-3):
依照上面的思路实现了一个简单版本的Hooks(可以局部更新)
from blog.
有毛病,如果我把state变成undefined,null,0, false这些的时候就会重置成initialState
from blog.
有毛病,如果我把state变成undefined,null,0, false这些的时候就会重置成initialState
确实 其实 useState()
在上下文中只有初始化hooks才会用吧,每一次初始化都是新的对象,state存在与否没有影响。
from blog.
有毛病,如果我把state变成undefined,null,0, false这些的时候就会重置成initialState
确实 其实
useState()
在上下文中只有初始化hooks才会用吧,每一次初始化都是新的对象,state存在与否没有影响。
没毛病,immutable模式
from blog.
一个组件内,react 是如何抓区和解析多个 useEffect 的
from blog.
一个组件内,react 是如何抓区和解析多个 useEffect 的
可以理解成每个组件内都会关联一个hooks队列
from blog.
一个组件内,react 是如何抓区和解析多个 useEffect 的
可以理解成每个组件内都会关联一个hooks队列
请问能讲下这块的工作原理吗
from blog.
unbro
楼主讲的算比较清楚了,具体实现可以看源码,啃不动的可以试试看这个简单的实现
from blog.
对这里不是很理解
Q:“Capture Value” 特性是如何产生的?
A:每一次 ReRender 的时候,都是重新去执行函数组件了,对于之前已经执行过的函数组件,并不会做任何操作。
困惑点在于:虽然每一次都会进行ReRender,但是如果都会从同一个memoizedState中取值的话,应该是能够获取到最新的值,不会存在“Capture Value” 特性
拜托大佬解惑~
from blog.
为什么 state声明在外面,点击的时候,view才变化,没想明白 @brickspert
因为每次重新render 的时候会重新执行 useState(0)呀,如果不放在外面的话,返回的state还是0
from blog.
Related Issues (20)
- 如何升级到 React 18 HOT 1
- React 18 对 Hooks 的影响:一
- React 18 总览 HOT 1
- 我认为 web3 是什么(大白话 web3) HOT 3
- React useEvent:砖家说的没问题
- Base64 编码原来这么简单 HOT 2
- issue一般啥时候用? HOT 1
- 我要去哪里?- 写在我的 30 岁 HOT 9
- 前端好还是后端好,看看7年前端和后端怎么说 HOT 2
- 只想做开源项目、技术项目,不想做业务,有办法吗?
- 前端小白半年准备进大厂
- 程序员如何实现财富自由 HOT 1
- 离职后聊一聊我眼中的蚂蚁 HOT 2
- 前端工程师个人的价值在哪里(换一个人能不能做?)【前端晋升必看】
- rm
- 2022 年:我在死亡边缘走过 HOT 4
- 前端质量体系之纸上谈兵 HOT 1
- 大白话虚拟货币理财原理 HOT 1
- 前端没了?也许是刚开始
- Telegram bot 和 mini apps 开发简易教程
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from blog.