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

开发 架构
本文主要从两个方面来探讨学习Hooks,第一解释Hooks难学的原因,第二给出学习Hooks的建议。

[[356931]]

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

  1. 类比ClassComponent的生命周期,学习Hooks的执行时机
  2. 慢慢熟练以后,发现Hooks的执行时机和生命周期又有些不同。比如componentWillReceiveProps对应哪个Hooks?
  3. 感到困惑,去搜一些Hooks原理层面的文章阅读

作为一个API,不该简简单单、可可爱爱的照着文档调用就行么,Hooks为什么这么难?

 

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

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

  1. 解释Hooks难学的原因
  2. 给出学习Hooks的建议

React的底层架构

可以用一个公式概括React:

  1. const UI = fn(state); 

视图可以看作状态经过函数的映射。

用户与界面的交互,可以看作这个公式的不断执行。

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

  1. const state = reconcile(update); 
  2. const UI = fn(state); 
  1. 用户交互产生update(更新)
  2. update经过reconcile步骤计算出当前应用的state
  3. fn将state映射为视图变化(UI)

我们给fn起个名字:commit:

  1. const state = reconcile(update); 
  2. const UI = commit(state); 

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

所以React的底层架构可以简化为三步:

  • 用户交互产生update
  • state = reconcile(update);
  • UI = commit(state);

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

生命周期函数的抽象层级

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

可以用计算机的抽象层级来类比:

  1. 高层:应用程序 
  2. 中层:操作系统 
  3. 底层:计算机组成架构 

对应React:

  1. 高层:应用程序       ClassComponent生命周期 
  2. 中层:操作系统       介入架构的API 
  3. 底层:计算机组成架构  React底层架构 

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

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

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

Hooks的抽象层级

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

  1. 高层:应用程序        
  2. 中层:操作系统       Hooks 
  3. 底层:计算机组成架构  React底层架构       

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

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

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

正是由于抽象层级的不对称,造成通过生命周期函数类比学习Hooks会遇到问题。

该怎么学Hooks

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

祭出我们的三步公式:

  • 用户交互产生update
  • state = reconcile(update);
  • UI = commit(state);

对照公式,我们来讲解几个常见hook的工作流程:

useState

举个例子:

  1. function App() { 
  2.   const [state, updateState] = useState(0); 
  3.   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

举个例子:

  1. useEffect(doSomething, [xx, yy]) 

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

  • UI = commit(state);

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

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

useLayout

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

useRef

以上例子可以看到,useState与useEffect分别在三步流程的不同步骤被触发,他们的触发时机是确定的。

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

useState作用于第一、二步,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技术揭秘[1](点击阅读原文)学习。

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

  • 从理念层面:代数效应与Hooks[2]
  • 从微观(代码)层面:所有常见Hooks的源码实现[3]

 

责任编辑:姜华 来源: 魔术师卡颂
相关推荐

2021-08-27 07:22:48

React组件前端

2010-04-21 14:25:22

bada三星

2024-02-19 00:10:00

AI模型

2022-06-07 08:59:58

hookuseRequestReact 项目

2023-07-13 09:05:57

react hook类型types

2021-10-22 15:45:32

开发技能React

2009-07-17 14:55:38

ibatis官方

2010-01-19 14:46:04

jQuery 1.4

2011-04-20 14:59:39

bada APIbada

2023-03-19 11:42:19

React新官方文档

2015-07-02 16:10:11

UIStackViewiOS 9

2020-12-01 15:54:08

鸿蒙构建系统

2012-12-18 09:25:20

2015-07-28 12:59:11

微软Windows 10指南

2017-05-25 12:30:44

AndroidApp开发架构

2011-03-17 08:58:09

数据储存Data StoragAndroid API

2020-11-16 10:50:27

KubernetesIngressLinux

2022-07-18 09:01:58

React函数组件Hooks

2024-01-07 20:10:11

Python编程语言

2017-03-16 13:38:02

MySQLMGR
点赞
收藏

51CTO技术栈公众号