useState原理
依然拿+1的button做例子
整个React的流程是
调用App()得到虚拟div,React会生成真实的div在页面中
当用户点击button时,调用setN(n+1),然后再次render
继续调用App(),此时得到新的虚拟div,通过DOM diff来更新真的div
每次调用App()都会运行useState(0)
分析
setN
setN一定会修改数据x,将n+1存入x
setN一定会触发重新渲染(re-render)
useState
useState会从x处读取n的最新值
x
每个组件都有自己的数据x,我们将其命名为state
尝试实现React.useState
自己定义一个useState函数命名为myUseState,接受一个初始值initialValue
声明一个函数setState,接受一个新的参数newState,并把newState的值赋给state,更新后实现更新UI要执行render。
因为myUseState会将state重制,所以这个变量要声明在外面
问题:如果一个组件用了两个useState怎么办
由于数据都存放在_state,所以会有冲突
改进思路
- 把_state做成一个对象
比如_state = {n:0,m:0}
不可以,因为useState(0)不知道变量是n还是m
- 把_state做成一个数组
比如_state=[0,0]
因为改成了一个数组所以后面需要加上下标index,同时对index进行自增。在render中将index重置为0.
这个方案的缺点
useState的调用顺序
若第一次渲染时,n是第一个,m是第二个,k是第三个
那么第二次渲染时必须保持一致
所以无法写在if里
总结
-
每个函数组件对应一个React节点
-
每个节点保存着index和state
-
useState会读取state[index]
-
index由useState出现的顺序决定
-
setState会修改state,并处罚更新