React源码分析(三):useState,useReducer

本文探讨React Hooks的内在机制,包括useState和useReducer的初始化与更新过程。解释了为什么在函数组件中需要Hooks,它们的执行时机,以及如何在组件状态管理中发挥作用。同时,详细阐述了Hooks的存储结构,以及useState和useReducer在不同阶段的行为,帮助理解React Hooks的工作原理。
摘要由CSDN通过智能技术生成

热身准备

在正式讲useState,我们先热热身,了解下必备知识。

为什么会有hooks

大家都知道hooks是在函数组件的产物。之前class组件为什么没有出现hooks这种东西呢?

答案很简单,不需要。

因为在class组件中,在运行时,只会生成一个实例,而在这个实例中会保存组件的state等信息。在后续的更新操作中,也只是调用其中的render方法,实例中的信息不会丢失。而在函数组件中,每次渲染,更新都会去执行这个函数组件,所以在函数组件中是没办法保存state等信息的。为了保存state等信息,于是有了hooks,用来记录函数组件的状态,执行副作用。

hooks执行时机

上面提到,在函数组件中,每次渲染,更新都会去执行这个函数组件。所以我们在函数组件内部声明的hooks也会在每次执行函数组件时执行。

在这个时候,可能有的同学听了我上面的说法(hooks用来记录函数组件的状态,执行副作用),又有疑惑了,既然每次函数组件执行都会执行hooks方法,那hooks是怎么记录函数组件的状态的呢?

答案是,记录在函数组件对应的fiber节点中。

两套hooks

在我们刚开始学习使用hooks时,可能会有疑惑, 为什么hooks要在函数组件的顶部声明,而不能在条件语句或内部函数中声明?

答案是,React维护了两套hooks,一套用来在项目初始化mount时,初始化hooks。而在后续的更新操作中会基于初始化的hooks执行更新操作。如果我们在条件语句或函数中声明hooks,有可能在项目初始化时不会声明,这样就会导致在后面的更新操作中出问题。

hooks存储

提前讲一下hooks存储方式,避免看晕了~~~

每个初始化的hook都会创建一个hook结构,多个hook是通过声明顺序用链表的结构相关联,最终这个链表会存放在fiber.memoizedState中:

var hook = {
   
    memoizedState: null,   // 存储hook操作,不要和fiber.memoizedState搞混了
    baseState: null,
    baseQueue: null,
    queue: null,    // 存储该hook本次更新阶段的所有更新操作
    next: null      // 链接下一个hook
};

而在每个hook.queue中存放的么个update也是一个链表结构存储的,千万不要和hook的链表搞混了。

接下来,让我们带着下面几个问题看文章:

  1. 为什么setState后不能马上拿到最新的state的值?
  2. 多个setState是如何合并的?
  3. setState到底是同步还是异步的?
  4. 为什么setState的值相同时,函数组件不更新?

假如我们有下面这样一段代码:

function App(){
   
  const [count, setCount] = useState(0)

  const handleClick = () => {
   
    setCount(count => count + 1)
  }

  return (
    <div>
        勇敢牛牛,        <span>不怕困难</span>
        <span onClick={
   handleClick}>{
   count}</span>
    </div>
  )
}

初始化 mount

useState

我们先来看下useState()函数:

function useState(initialState) {
   
  var dispatcher = resolveDispatcher();
  return dispatcher.useState(initialState);
}

上面的dispatcher就会涉及到开始提到的两套hooks的变换使用,initialState是我们传入useState的参数,可以是基础数据类型,也可以是函数,我们主要看dispatcher.useState(initialState)方法,因为我们这里是初始化,它会调用mountState方法:

function mountState(initialState) {
   
  var hook = mountWorkInProgressHook(
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值