大家好,我是若川。今天分享一篇关于「React Hooks」的好文。欢迎点击下方卡片关注我。

以下是正文~


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

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

  2. 慢慢熟练以后,发现Hooks的执行时机和生命周期又有些不同。比如componentWillReceiveProps对应哪个Hooks

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

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

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

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

  1. 解释Hooks难学的原因

  2. 给出学习Hooks的建议

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作用于第一、二步,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]

参考资料

[1]

React技术揭秘: https://react.iamkasong.com/

[2]

代数效应与Hooks: https://react.iamkasong.com/process/fiber-mental.html

[3]

所有常见Hooks的源码实现: https://react.iamkasong.com/hooks/structure.html

最近组建了一个江西人的前端交流群,如果你也是江西人可以加我微信 ruochuan12 拉你进群。


················· 若川出品 ·················

今日话题

vue-devtools工具中可以「根据组件直接打开对应文件」,多少人知道或者用过呢。

一个愿景是帮助5年内前端人走向前列的公众号

可加我个人微信 ruochuan12,长期交流学习

推荐阅读

我在阿里招前端,我该怎么帮你?(现在还能加我进模拟面试群)

如何拿下阿里巴巴 P6 的前端 Offer

跟着官方文档能学懂React Hooks就怪了相关推荐

  1. Kubernetes教程之跟着官方文档从零搭建K8S

    本文将带领读者一起, 参照着 Kubernetes 官方文档,对其安装部署进行讲解.Kubernetes更新迭代很快,书上.网上等教程可能并不能适用于新版本,但官方文可以. Kubernetes 教程 ...

  2. 【读官方文档,学原味技术】SpringBoot-Staters和自定义Starter

    spring-boot-reference 如果不想阅读英文原文,你可以直接读本文的[TS]标注参考翻译内容.由于本人水平有限,如有理解错误,烦请指正,互相交流. Lire les documents ...

  3. 跟着官方文档学DGL框架第一天——DGL概览

    主要参考:https://docs.dgl.ai/tutorials/basics/1_first.html DGL是什么 DGL是一种用于简化图神经网络实现的包,感觉官方文档写得很亲民,打算好好拜读 ...

  4. 跟着官方文档一步一步搭建基于gozero的微服务

    1. 创建项目 mkdir microservice cd microservice go mod init zzh.com/microservice 2. 下载go-zero和goctl 2.1 设 ...

  5. k8s多master建议用几个_Kubernetes 教程之跟着官方文档从零搭建 K8S

    前言 本文将带领读者一起, 参照者 Kubernetes 官方文档, 对其安装部署进行讲解. Kubernetes 更新迭代很快, 书上.网上等教程可能并不能适用于新版本, 但官方文档能. 阅读这篇文 ...

  6. 跟着官方文档学DGL框架第七天——下载和处理数据集

    参考链接 https://docs.dgl.ai/guide/data.html#guide-data-pipeline https://docs.dgl.ai/en/0.5.x/_modules/d ...

  7. 【pytest官方文档】解读- 开发可pip安装的第三方插件

    在上一篇的 hooks 函数分享中,开发了一个本地插件示例,其实已经算是在编写插件了.今天继续跟着官方文档学习更多知识点. 一个插件包含一个或多个钩子函数,pytest 正是通过调用各种钩子组成的插件 ...

  8. react router官方文档_阿里开源可插拔 React 跨端框架 UmiJS

    点击上方"开发者技术前线",选择"星标" 18:30 在看 真爱 作者:Tamic  |  编辑: 可可 阿里之前开源:阿里闲鱼开源 Flutter 应用框架 ...

  9. 一起学微软Power BI系列-官方文档-入门指南(2)获取源数据

    阅读目录 1.系列文章说明 2.入门指南(2)获取数据源 3.资源 我们在文章: 一起学微软Power BI系列-官方文档-入门指南(1)Power BI初步介绍中,我们介绍了官方入门文档的第一章.今 ...

最新文章

  1. ZJU-java进阶笔记 第三周(对象容器)
  2. step1.day11 C语言基础练习之指针和二级指针
  3. 前端学习(1658):前端系列实战课程之图片延迟加载思路
  4. Python之if语句
  5. MongoDB:MapReduce基础及实例
  6. 使用 Python 和 Flask 实现 RESTful services
  7. 12. JavaScript Number 对象
  8. 操作系统 进程(上)
  9. ElasticSearch
  10. 戴尔 DELL Inspiron N4050硬件升级及系统安装方面相关的问题阐述与解决思路
  11. ssh: connect to host master port 22: No route to host
  12. 计算机课反思的作文600字,中考反思作文600字6篇
  13. 【图像隐藏】基于matlab像素预测和位平面压缩的加密图像可逆数据隐藏【含Matlab源码 2218期】
  14. js实现简单的点名器随机色
  15. 进程线程(六) 深度睡眠 和 浅度睡眠
  16. Vista硬盘安装详细图解
  17. 既不是研发顶尖高手,也不是销售大牛,为何偏偏获得2万RMB的首个涛思文化奖?...
  18. 一岁半女娃海中“游泳秀” 观众含泪观看
  19. 【转】bit、Byte、bps、Bps、pps、Gbps的单位详细说明及换算
  20. Cocos Creator—定制H5游戏首页loading界面 1

热门文章

  1. sybase数据库导出mysql_使用BCP从Sybase远程数据库中导出数据
  2. 1 vmware 如何联网,以及行命令令初步
  3. 【UOJ#246】套路(动态规划)
  4. 素数对猜想之python3实现
  5. NSTimer定时器进阶——详细介绍,循环引用分析与解决
  6. 2/19 福建四校联考
  7. 【Python】Python Mako模板使用
  8. 第一次写python
  9. poj 2696 A Mysterious Function
  10. 安卓APP_ Fragment(1)—— Fragment概念、基础用法、动态变换、管理栈