跟着官方文档能学懂Hooks就怪了

回想下你入门Hooks的过程,是否是经历过:html

  1. 类比ClassComponent的生命周期,学习Hooks的执行时机前端

  2. 慢慢熟练之后,发现Hooks的执行时机和生命周期又有些不一样。好比componentWillReceiveProps对应哪一个Hooksreact

  3. 感到困惑,去搜一些Hooks原理层面的文章阅读数组

做为一个API,不应简简单单、可可爱爱的照着文档调用就行么,Hooks为何这么难?markdown

React官方也发现了这个问题,在React要重写文档了讲到,React要基于Hooks重写文档。架构

本文主要包括2方面内容:app

  1. 解释Hooks难学的缘由异步

  2. 给出学习Hooks的建议ide

React的底层架构

能够用一个公式归纳React函数

const UI = fn(state);
复制代码

视图能够看做状态通过函数的映射。

用户与界面的交互,能够看做这个公式的不断执行。

这个公式太精简了,没有解释state(状态)从哪儿来,咱们扩展下:

const state = reconcile(update);
const UI = fn(state);
复制代码
  1. 用户交互产生update(更新)

  2. update通过reconcile步骤计算出当前应用的state

  3. fnstate映射为视图变化(UI)

咱们给fn起个名字:commit

const state = reconcile(update);
const UI = commit(state);
复制代码

那么update在哪里产生呢?固然来自于用户交互,好比:点击事件。

因此React的底层架构能够简化为三步:

  • 用户交互产生update

  • state = reconcile(update);

  • UI = commit(state);

了解了底层架构,咱们再来看经过类比ClassComponent学习Hooks会带来的问题。

生命周期函数的抽象层级

咱们已经有了完整的驱动视图更新的底层架构,开发者该怎么操做这套架构呢?

能够用计算机的抽象层级来类比:

高层:应用程序
中层:操做系统
底层:计算机组成架构
复制代码

对应React

高层:应用程序       ClassComponent生命周期
中层:操做系统       介入架构的API
底层:计算机组成架构  React底层架构
复制代码

能够看到,生命周期函数属于抽象程度比较高的层次。这么设计也是为了让开发者更容易上手React

设想一个Vue2开发者要转React技术栈,只须要类比Vue的生命周期来学习React的生命周期就好了。

这一切在Hooks到来前都没问题,然而......

Hooks的抽象层级

Hooks属于中等抽象层级。也就是说,Hooks直接介入底层架构的运行流程。

高层:应用程序       
中层:操做系统       Hooks
底层:计算机组成架构  React底层架构      
复制代码

当咱们用生命周期函数来类比Hooks时,实际上是用高抽象层级的事物来描述低抽象层级的事物。

动物 --> 哺乳动物 --> 牛 --> 奶牛

对于一个只见过奶牛,再没见过其余动物的人,你怎么向他解释哺乳动物是啥?

正是因为抽象层级的不对称,形成经过生命周期函数类比学习Hooks会遇到问题。

该怎么学Hooks

既然Hooks属于中等抽象层,离底层很近,那么更好的学习方式是经过底层向上学习。

祭出咱们的三步公式:

  • 用户交互产生update

  • state = reconcile(update);

  • UI = commit(state);

对照公式,咱们来说解几个常见hook的工做流程:

useState

举个例子:

function App() {
  const [state, updateState] = useState(0);
  return <div onClick={() => updateState(state + 1)}></div>;
}
复制代码

useState返回值数组包含:

  1. 保存的state

  2. 改变state的方法updateState

对照公式,state属于公式步骤2计算得出的:

  • state = reconcile(update);

此时视图尚未更新。

用户点击div触发updateState,对应公式步骤1:

  • 用户交互产生update

因此调用updateState能开启底层架构的三步运行流程。

reconcile计算出state后就会进入第三步:

  • UI = commit(state);

最终渲染视图。

useEffect

举个例子:

useEffect(doSomething, [xx, yy])
复制代码

useEffect的回调函数doSomething在第三步执行完成后异步调用:

  • UI = commit(state);

因此在doSomething函数内部能获取到完成更新的视图。

第二个参数[xx, yy]做为依赖项,决定了doSomething是否会被调用。

useLayoutEffect

不一样于useEffect在第三步执行完成后异步调用,useLayoutEffect会在第三步执行完UI操做后同步执行。

useRef

以上例子能够看到,useStateuseEffect分别在三步流程的不一样步骤被触发,他们的触发时机是肯定的。

那么这三个步骤如何交流呢?经过useRef

useState做用于第1、二步,useLayoutEffect做用于第三步,useEffect做用于第三步完成后。

使用useRef,就能达到在不一样步骤间共享引用类型数据的目的。

能够看到,React为底层架构三步工做流程的每一步提供了对应的hook,同时提供了串联这三步工做流程的hook

开发者只须要根据业务须要,经过基础Hooks组装出自定义hook,就能在底层架构运行流程的各个时期运行逻辑。

自底向上学习是本末倒置么?

有同窗会反驳:以前学React得学生命周期函数的执行时机,如今学Hooks得学底层架构运行流程。难道不是本末倒置,更复杂了么?

其实否则。我问你几个问题:

  1. componentWillReceiveProps为何被标记为unsafe

  2. getDerivedStateFromProps用过么?

  3. this.setState是同步仍是异步的?

这些和生命周期函数相关的问题一点都不简单!不少用了几年React的前端不必定回答的上。

做为高层次抽象,生命周期函数隐藏了太多实现细节。同时React又太灵活,不像Vue经过模版语言限制了开发者的操做。

结果就是:不一样React开发者写出各类奇奇怪怪的ClassComponent

反观经过底层架构运行流程学习Hooks

  • 底层架构运行流程就是React的绝对真理,不会隐藏更多抽象

  • Hooks的写法规范限制了开发者的奇葩操做

这里的惟一问题,就是缺乏一份从底层出发的文档。这也是React要重写文档的初衷。

对于熟练使用React的开发者,在官方新文档出来前,能够参考React技术揭秘学习。

这里再提供些其余视角聊Hooks的文章:

相关文章
相关标签/搜索