useState这个hooks在不同的运行阶段执行的不是一个函数:

1.mount阶段(第一次执行);

执行的就是mountState。

image-20220915122219644

执行mountWorkInProgressHook,这个函数的作用就是生成一个hooks对象。

image-20220915122426402

image-20220915122545288

我们拿到的状态都保存在memoizedState,(同步模式下的时候这个值没啥用)baseState主要是为了保存高优先级打断低优先级更新时的状态值(这两个值并不总是相等的),保证在低优先级的更新下次运行时,能够还原状态的值,(React只保证最终的状态是正确的,中间的状态可能会跳变(一般界面上不会看到跳变的状态)。

下面就是做一些hook的初始化。我们后面执行的setState就是这个dispatchAction函数。

image-20220915123153652

2.update阶段

image-20220915123408803

更新阶段执行的是updateReducer(也就是useReducer这个hooks的更新阶段的函数, 这个hooks的思想和redux的reducer一模一样,践行的就是纯函数的思想),只是这里传入了一个basicStateReducer,长下面这样,

也就是判断你传给setState里面是不是个函数,是函数就执行函数,并返回函数的返回值,不是函数,就直接返回值。

image-20220915123529537


下面是调用setState的过程

所有的setState(函数式组件, 类式组件调的不是这个函数,但是做的事情都差不多),

先是根据本次更新生成一个update对象。如下图。

image-20220915123846881

之后就把这个update对象挂到queue.pengding这个环状链表上,指针指向的是链表的最后一个节点。

image-20220915124250007

image-20220915124354756

然后通过scheduleUpdateOnFiber调度本次更新

image-20220915124447426

因为react的更新都是需要遍历整个虚拟dom树的。所以需要先从当前节点往上找,找到当前应用的根节点,也就是调用ReactDOM.render的app组件。

之后通过这个performSyncWorkOnRoot(同步更新是这个函数,有优先级的那种方式就是调用的performConcurrentWorkOnRoot,react18默认就是这种模式),开始本轮的更新。

image-20220915124626132

performSyncWorkOnRoot -> renderRootSync -> workLoopSync

这个workLoopSync函数就会从根节点,递归的遍历整颗虚拟DOM.

执行diff算法

image-20220915125200383

这个workInprogress会在这个过程中从根节点一直到叶节点(DFS),每一个节点的diff做完之后workInprogress = workInprogress.child

image-20220915125333188

performUnitOfWork把每一个节点的diff过程又分为递阶段beginWork(创建/复用fiber节点),和归阶段completeUnitOfWork(创建/复用DOM节点,还没挂到页面,相当于fragment)

image-20220915125914730