Hooks原理

47 阅读2分钟

useState原理

依然拿+1的button做例子

image.png

整个React的流程是

82d75e6af4756eca73d52e060012448d.jpeg

调用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

image.png

自己定义一个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]

image.png

因为改成了一个数组所以后面需要加上下标index,同时对index进行自增。在render中将index重置为0.

这个方案的缺点

useState的调用顺序

若第一次渲染时,n是第一个,m是第二个,k是第三个

那么第二次渲染时必须保持一致

所以无法写在if里

image.png

总结

  • 每个函数组件对应一个React节点

  • 每个节点保存着index和state

  • useState会读取state[index]

  • index由useState出现的顺序决定

  • setState会修改state,并处罚更新