回想下你入门Hooks
的过程,是否是经历过:html
类比ClassComponent
的生命周期,学习Hooks
的执行时机前端
慢慢熟练之后,发现Hooks
的执行时机和生命周期
又有些不一样。好比componentWillReceiveProps
对应哪一个Hooks
?react
感到困惑,去搜一些Hooks
原理层面的文章阅读数组
做为一个API
,不应简简单单、可可爱爱的照着文档调用就行么,Hooks
为何这么难?markdown
React
官方也发现了这个问题,在React要重写文档了讲到,React
要基于Hooks
重写文档。架构
本文主要包括2方面内容:app
解释Hooks
难学的缘由异步
给出学习Hooks
的建议ide
能够用一个公式归纳React
:函数
const UI = fn(state);
复制代码
视图
能够看做状态
通过函数
的映射。
用户与界面的交互,能够看做这个公式的不断执行。
这个公式太精简了,没有解释state
(状态)从哪儿来,咱们扩展下:
const state = reconcile(update);
const UI = fn(state);
复制代码
用户交互产生update
(更新)
update
通过reconcile
步骤计算出当前应用的state
fn
将state
映射为视图变化(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
底层:计算机组成架构 React底层架构
复制代码
当咱们用生命周期函数
来类比Hooks
时,实际上是用高抽象层级
的事物来描述低抽象层级
的事物。
动物 --> 哺乳动物 --> 牛 --> 奶牛
对于一个只见过奶牛,再没见过其余动物的人,你怎么向他解释哺乳动物
是啥?
正是因为抽象层级的不对称,形成经过生命周期函数
类比学习Hooks
会遇到问题。
既然Hooks
属于中等抽象层,离底层很近,那么更好的学习方式是经过底层向上学习。
祭出咱们的三步公式:
用户交互产生update
state
= reconcile(update
);
UI
= commit(state
);
对照公式,咱们来说解几个常见hook
的工做流程:
举个例子:
function App() {
const [state, updateState] = useState(0);
return <div onClick={() => updateState(state + 1)}></div>;
}
复制代码
useState
返回值数组包含:
保存的state
改变state
的方法updateState
对照公式,state
属于公式步骤2计算得出的:
此时视图尚未更新。
用户点击div
触发updateState
,对应公式步骤1:
update
因此调用updateState
能开启底层架构的三步运行流程。
当reconcile
计算出state
后就会进入第三步:
UI
= commit(state
);最终渲染视图。
举个例子:
useEffect(doSomething, [xx, yy])
复制代码
useEffect
的回调函数doSomething
在第三步执行完成后异步调用:
UI
= commit(state
);因此在doSomething
函数内部能获取到完成更新的视图。
第二个参数[xx, yy]
做为依赖项,决定了doSomething
是否会被调用。
不一样于useEffect
在第三步执行完成后异步调用,useLayoutEffect
会在第三步执行完UI
操做后同步执行。
以上例子能够看到,useState
与useEffect
分别在三步流程的不一样步骤被触发,他们的触发时机是肯定的。
那么这三个步骤如何交流呢?经过useRef
。
useState
做用于第1、二步,useLayoutEffect
做用于第三步,useEffect
做用于第三步完成后。
使用useRef
,就能达到在不一样步骤间共享引用类型数据的目的。
能够看到,React
为底层架构三步工做流程的每一步提供了对应的hook
,同时提供了串联这三步工做流程的hook
。
开发者只须要根据业务须要,经过基础Hooks
组装出自定义hook
,就能在底层架构运行流程的各个时期运行逻辑。
有同窗会反驳:以前学React
得学生命周期函数
的执行时机,如今学Hooks
得学底层架构运行流程
。难道不是本末倒置,更复杂了么?
其实否则。我问你几个问题:
componentWillReceiveProps
为何被标记为unsafe
?
getDerivedStateFromProps
用过么?
this.setState
是同步仍是异步的?
这些和生命周期函数
相关的问题一点都不简单!不少用了几年React
的前端不必定回答的上。
做为高层次抽象,生命周期函数
隐藏了太多实现细节。同时React
又太灵活,不像Vue
经过模版语言
限制了开发者的操做。
结果就是:不一样React
开发者写出各类奇奇怪怪的ClassComponent
。
反观经过底层架构运行流程
学习Hooks
:
底层架构运行流程
就是React
的绝对真理,不会隐藏更多抽象
Hooks
的写法规范限制了开发者的奇葩操做
这里的惟一问题,就是缺乏一份从底层
出发的文档。这也是React
要重写文档的初衷。
对于熟练使用React
的开发者,在官方新文档出来前,能够参考React技术揭秘学习。
这里再提供些其余视角聊Hooks
的文章:
从理念
层面:代数效应与Hooks
从微观
(代码)层面:全部常见Hooks的源码实现