Hook入门学习 | 青训营笔记

86 阅读6分钟

这是我参与「第四届青训营 」笔记创作活动的的第6天 入门React,学习 Hooks 的前世今生

React 概述

React 中文意思是“反应”或者“响应”,这正是 React 的核心原理:当数据发生变化时,UI能够自动把变化反映出来

在 React 之前,我们需要调用 DOM 的 API 来修改 DOM 树的结构,从而改变 UI 的展 现。而在有了 React 之后,我们只需要在业务状态和 UI 状态之间建立一个绑定的关系就 行了。绑定完成后,我们就不需要再关心怎么去精细控制 UI 的变化,因为 React 会在数 据发生变化时,帮助我们完成 UI 的变化。

image.png

基本概念

要理解React,最重要的是去理解组件、状态和JSX的概念。

使用组件的方式描述UI

在React 中所有UI都是通过组件来组成的,这样所有的UI元素都可以分成两种

  1. 内置组件,内置组件就是映射到HTML节点的组件,例如div,input等,都是小写字母
  2. 自定义组件,自定义组件就是自己创建的组件,使用必须以大写字母开头,例如TopicList。

这样就可以把UI上的复杂场景模块化为独立的组件,可以更加直观、更容易维护和复用。

使用 state 和 props 管理状态

React 的核心机制是能够在数据发生变化的时候自动重新渲染 UI,那 么势必要有一个让我们保存状态的地方,这个保存状态的机制就是 state。而 props 就是 类似于 Html 标记上属性的概念,是为了在父子组件之间传递状态。 我们可以使用 useState 这样一个 Hook 来保存状态,那么状态在发生变 化时,也会让 UI 自动发生变化。

const [count, setCount] = React.useState(0);

创建了一个叫 count 的state ,通过setCount 方法来改变 count,因为state是只读属性我们只能通过特殊的方法来改变它的值

JSX

JSX是 React 中的“模版语言”,能够在 Javascript 中使用 HTML 的标记写法。 通过 createElement 这个 API,我们可以构建出需要的组件树,而 JSX 只是让这 种描述变得更加直观和高效。所以我们说 JSX 其实是一种语法糖。理解这一点非常重要, 因为它意味着两点:

  1. JSX 的表达能力等价于 JavaScript 的表达能力,那么所有我们可能需要的机制,比如循 环、条件语句等等,JSX 其实都能灵活表达。
  2. JSX 几乎不需要学习,只要你会用 JavaScript,就也会用 JSX。

查看实例

React 为什么要带来 Hooks

React 还是在3年前的 16.8 版本中推出了一套全新的 Hooks 机制。 其实对于 React 开发而言,这只是多了一个选择。因为原来的基于 Class 的组件完全可以 继续使用,这意味着这两种开发方式可以并存,已有代码不需要做任何改动,而新的代码 可以根据具体情况采用 Hooks 的方式来实现就行了。 所以一定你一定会有这样的疑问,为什么要 发明 Hooks;以及它所解决的问题是什么。

重新思考 React 组件的本质

React 组件的模型其实很直观,就是从 Model 到 View 的映射,这里的 Model 对应到 React 中就是 state 和 props。如下图所示:

image.png
在过去,我们需要处理当 Model 变化时,DOM 节点应该如何变化的细节问题。而现在,我们只需要通过 JSX,根据 Model 的数据用声明的方式去描述 UI 的最终展现就可以了, 因为 React 会帮助你处理所有 DOM 变化的细节。而且,当 Model 中的状态发生变化时,UI 会自动变化,即所谓的数据绑定。
所以呢,我们可以把 UI 的展现看成一个函数的执行过程。其中,Model 是输入参数,函数的执行结果是 DOM 树,也就是 View。而 React 要保证的,就是每当 Model 发生变化所以呢,我们可以把 UI 的展现看成一个函数的执行过程。其中,Model 是输入参数,函 数的执行结果是 DOM 树,也就是 View。而 React 要保证的,就是每当 Model 发生变化时,函数会重新执行,并且生成新的 DOM 树,然后 React 再把新的 DOM 树以最优的方式更新到浏览器。
React 中其实是没有利用到 Class 的继承特性的。体现在这两个方面:

  • 一方面,React 组件之间是不会互相继承的。所以说,React 中其实是没有利用到 Class 的继承特性的。
  • 另一方面,因为所有 UI 都是由状态驱动的,因此很少会在外部去调用一个类实例(即组件)的方法。要知道,组件的所有方法都是在内部调用,或者作为生命周期方法被自动调用的。

因为所有的 UI 都是声明出来的,不用处理细节的变 化过程。因此,通过函数去描述一个组件才是最为自然的方式。这也是为什么 React 很早 就提供了函数组件的机制。

只是当时有一个局限是,函数组件无法存在内部状态,必须是纯函数,而且也无法提供完整的生命周期机制。这就极大限制了函数组件的大规模使用。

Hooks 是如何诞生的?

如果我们想要让函数组件更有用,目标就是给函数组件加上状态。

那我们是不是就是需要这样一个机制,能够把一个外部的数据绑定到函数的 执行。当数据变化时,函数能够自动重新执行。这样的话,任何会影响 UI 展现的外部数据,都可以通过这个机制绑定到 React 的函数组件。

这个机制就是 Hooks 。在 React 中,Hooks 就是把某个目标结果钩到某个可能会变化的数据源或者事件源上,那么当被钩到的数据或事件发生变化时,产生这个目标结果的代码会重新执行,产生更新后的结果

Hooks 带来的好处:逻辑复用

在 Class 组件中,我们要实现逻辑服用,只能依靠高阶组件来实现,这样就会带来一些缺点,比如:

  1. 代码难理解,不直观,很多人甚至宁愿重复代码,也不愿用高阶组件;
  2. 会增加很多额外的组件节点。每一个高阶组件都会多一层节点,这就会给调试带来很大的负担。

Hooks 带来的好处:关注分离

Hooks 能够让针对同一个业务逻辑的代码尽可能聚合在一块儿。这是过去在 Class 组件中 很难做到的。因为在 Class 组件中,你不得不把同一个业务逻辑的代码分散在类组件的不同生命周期的方法中。

image.png 图的左侧是 Class 组件,右侧是函数组件结合 Hooks。蓝色和黄色代表不同的业务功能。 可以看到,在 Class 组件中,代码是从技术角度组织在一起的,例如在 componentDidMount 中都去做一些初始化的事情。而在函数组件中,代码是从业务角度组织在一起的,相关代码能够出现在集中的地方,从而更容易理解和维护。