react hooks源代码总体运行初解(一)

2,375 阅读3分钟

作者:知鸟 聂凡坤

这篇文章是从源代码的角度剖析react hooks,在开始之前,对于react hooks的重要性以及为什么需要用函数组件可以阅读:

一、阅读源码的误区

首先我们需要找到源代码,不少萌新小伙伴可能会从node_modules中的react模块包中去找hooks的源代码,如下图

node_modules中react源码

你所看到的只有这些hooks的定义,而其值的实现方式都是以var dispatcher = resolveDispatcher();再由这个dispatcher去调用对应的不同的事件,对于resolveDispatcher()方法的实现也会看得一头雾水,ReactCurrentDispatcher在这个源代码中啥都没有。所以从node_modules中react模块包解读hooks是行不通的。

resolveDispatcher方法定义

二、从哪里开始阅读源码

正确的方式是从github react 的仓库下载源代码仓库能进行解读。下载好了之后我们可以看到packages有32个模块包,接下来的讲解都在packages路径下,跟hooks强相关的reactreact-reconciler两个模块包。

文件路径react/src/ReactHooks.js

上面的图可以看到这是真正意义上的专门的定义react hooks的本源,再继续寻找ReactCurrentDispatcher我们可以看到是引入了一个类型Dispatcher(派发者),派发者类型定义如图:

派发者(类型定义)

派发者的实现方式

如上文件只暴露出的type Dispatcher里只提供了常用的如useStateuseEffect等方法的类型定义,怎样才能发现更多有用的信息呢?

三、如何快速定位方法的源码实现

源代码研究不下去的时候应该换个角度,既然是只是定义类型,那一定有其他地方也会调用该类型从而获取hooks的更深层的实现。所以这里用了一个取巧的方式:在react-reconciler中搜索Dispatcher

Dispatcher

可以看到两个文件引用了ReactInternalTypes中定义的Dispatcher打开ReactFiberHooks.old.js之后就可以发现新大陆。

reactFiberHooks.old.js

这里可以看到引入类Dispatcher的实现有三个对象HooksDispatcherOnMount(hooks派发在组件加载时),HooksDispatcherOnUpdate(hooks派发在组件更新时),HooksDispatcherOnRerender(hooks派发在组件渲染。这三个对象都是集中在renderWithHooks的函数之中(图不贴,请读者自行寻找)。

renderWithHooks使用文件

本着追本溯源的方式我们找寻renderWithHooks的引用文件。在ReactFiberBeginWork.old.js中都使用在了updateFunctionComponent函数中,而这个函数是调用在了case FunctionComponent中,而代码下方的case ClassComponent所调用的方法的的updateClassComponent,所以,如下

函数组件调用及其实现

由于找到代码是采用的取巧的方式,再回过头总结下hooks的实现为一个词--分片任务调度。对于分片这个词感到陌生的小伙伴可以拜读下这篇文章

这篇文章中有提到两个阶段,Reconcile阶段和Commit阶段从这两个阶段分别对应ReactFiberBeginWork.old.jsReactFiberCommitWork.old.js(现在文件中oldnew代码都一样,可能facebook官方要做优化重构所以复制一份出来用old,new作为区分)。

四、在reconcile阶段调用核心方法renderWithHooks

reconcile阶段当解析到为函数组件时会调用核心方法renderWithHooks

此方法会根据当前的分片任务中的current属性是否有任务去判断执行HooksDispatcherOnMount还是HooksDispatcherOnUpdate,在渲染阶段react调度器会适时得执行HooksDispatcherOnRerender

五、在commit阶段对hook执行队列解除

commit阶段当解析到为函数组件时会对hook执行队列解除:

对于commitHookEffectListUnmount字面意思为解除提交过的hooks执行队列,将当前的一个个执行的hooksEffect置空或者销毁。

文章篇幅有限,蜻蜓点水,只对hooks怎么通过react的调度机制运行以及如何找寻hooks的源码进行解读,整体运行的机制还需要各位看官自行再看源代码解读。

下一个篇幅将介绍hooks的那些方法源码的实现。