React v16.7 "Hooks" - What to Expect
什么是 Hooks?
Hooks 是一个 React 函数组件内一类特殊的函数(通常以 “use” 开头,比如 “useState”),使开发者能够在 function component 里依旧使用 state 和 life-cycles,以及使用 custom hook 复用业务逻辑。
动机
在 React 里,function component 就是一个 pure render component,没有 state 和 component life-cycle。如果需要这两个中的任意一个,就需要变成 class component。在既有的 React API 下,这个模式有如下一些缺点:
组件间交流的耦合度很高,组件树臃肿
在既有的模式下,React 的组件间通信无非是两种,一种是单项数据流,另一种是通过 redux 之类的 global store 来实现全局状态和各组件间的解耦。当有些状态不适合放在 global store 的情况下,组件间逻辑的复用和沟通就变得十分困难(必须一层一层往下传)。这一点在 Higher order component (高阶组件) 和 render props 中尤其常见。我们为了复用一些逻辑,单独创造了很多 HOC(高阶组件) 来向下传递状态。这导致的问题就是当我们的应用规模变得越来越大的时候,一些无关 UI 的 wrapper 组件越来越多,React 组件树变得越来越臃肿(在 devtool 中可以甚至看到数十层 wrapper)。某些业务场景下,一个 Tooltip component 里面都嵌套了三四层额外的组件,使开发和调试的效率变得很低。
在新的 React hook 中,我们可以创建 custom hook,在其中复用一些逻辑,这些逻辑不再出现在组件树中,而是成为一个单独的,独立的逻辑单元,但是他们仍然响应 React 在渲染之间的变化。
JavaScript 的 class 产生的诸多疑惑
这一点是相对于 JavaScript 来说的。还记得刚入门 JavaScript 的时候,需要跨越的一个重要难关就是 ”this” 指向,以及原型链,继承这些问题。即使我们真正觉得明白了其中的原理,在日常的开发中也难免因为疏忽而踩坑,这一系列的问题导致新手相对比较难上手 React。举个简单的例子,React 组件内的 event listener 之前需要手动 bind this 的问题,这个问题就很难对一个 JavaScript 入门的新手解释明白。
而这一系列的问题,将在 Hook 中被极大地解决。如果没有 class,没有了 this,可能上述的种种问题都不再是问题了。
Write Hooks
说了这么多,Hooks API 是什么样呢?首先需要声明的是,Hooks 是向后兼容的,class component 不会被移除。作为开发者,可以慢慢迁移到这个新的 API。
Hooks 主要分为三种:
● State hooks (在 function component 中使用 state)● Effect hooks (在 function component 中使用生命周期和 side effect)
● Custom hooks (自定义 hooks 用来复用组件逻辑,解决了上述的第一个动机中阐述的问题,这一部分就不在此多费篇幅介绍了,请大家移步文档)。
State hooks
import { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
之前讲过 hook 本质是一个特殊的函数(通常以 “use” 开头)。在这里,”useState” 就是一个 hook,通过它我们能够嵌入组件内部的 state。这个函数返回一个 pair,第一个值是当前对应这个 hook 的 state 值,第二个是怎样更新这个值。
我们可以从中感觉到,这两个返回值分别对应的以前的用法是:
● this.state● this.setState
除此之外,我们还可以在一个函数组件中使用多个 useState:
function ExampleWithManyStates() {
// Declare multiple state variables!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
// ...
}
这给我们的一个非常大的好处就是我们能够避免组件的 state 结构过于臃肿(因为之前每个 component class 只能有一个 state),能够独立处理每个 state。另一个好处就是这种写法非常直观,一眼就可以看出和这个 state 相关的两个变量,比如 [age, setAge]。
Effect hooks
import { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
我们还需要解决一个问题,那就是怎样在 function component 里使用 life-cycles,生命周期函数。在这里,所有的 life-cycles,比如 componentDidMount, componentDidUpdate, shouldUpdate, 等等都集合成一个 Hook,叫做 useEffect。这个函数类似 redux 中的 subscribe,每当 React 因为 state 或是 props 而重新 render 的之后,就会触发 useEffect 里的这个 callback listener(在第一次 render 和每次 update 后触发)。
为什么叫 useEffect 呢?因为我们通常在生命周期内做的操作很多都会产生一些 side-effect(副作用)的操作,比如更新 DOM,fetch 数据,等等。
Other Built-in Hooks
除了 useState, useEffect 还有另外一些 React 自带的 hooks。比如:
● useContext替代了 <Context.Consumer> 使用 render props 的写法,使组件树更加简洁。
● useReducer相当于组件自带的 redux reducer,负责接收 dispatch 分发的 action 并更新 state。
详细用法请看文档。
总结
读到这里,你可能理解了为什么这个新的 API 被叫做 “Hooks” 了。”Hooks” 本意是”钩子“的意思。在 React 里,hooks 就是一系列特殊的函数,使函数组件 (functional component) 内部能够”钩住“ React 内部的 state 和 life-cycles。
这个向后兼容的 API 在解决了一些既有问题的情况下,不仅使我们能够更好地使用 state 和 life-cycles,真正功能强大的地方是使我们能够更轻松地复用组件逻辑(custom hooks)。但是限于篇幅,很多功能强大的部分和一些注意事项在这篇文章里并没有过多讲解,请大家移步官方文档学习更详细的姿势(墙裂推荐)。
原文发布时间为:2018-11-02
本文作者:cyan
本文来自云栖社区合作伙伴“前端大学”,了解相关信息可以关注“前端大学”。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
类的加载机制
目录介绍 01.Java对象的创建过程 1.0 看下创建类加载过程 1.1 对象的创建 1.2 对象的内存布局 02.Java内存区域 2.0 运行时数据区域 2.1 程序计数器 2.2 虚拟机栈 2.3 本地方法栈 2.4 Java堆 2.5 方法区 2.6 运行时常量池 2.7 直接内存 03.Java对象的访问定位方式 3.1 句柄 3.2 直接指针 04.Java对象销毁分析 4.1 JVM内存分配与回收 4.2 判断对象是否死亡 4.3 不可达的对象并非“非死不可” 4.4 如何判断一个常量是废弃常量 4.5 如何判断一个类是无用的类 4.6 GC回收算法详解 05.String类和常量池 5.1 String对象的两种创建方式 5.2 String类型的常量池 好消息 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计47篇[近2...
- 下一篇
个税起征点上调至5000,用Python算一算少交多少税
今天出了一个重磅消息,个税起征点从3500上调到5000啦! 广大IT农民工的生活压力又减轻了一些,有没有 晚上加一个鸡腿,要不要~ 开心归开心,我们来用Python算一算,新的规则下,我们需要交多少税,比原先少交多少税。 下面的这张表是税率表,这是对超过免征额部分的收入征收的税率 这次调整的是免征额,之前是3500,现在是5000,税率部分没有发生变化。 我们用Python来写两个程序,一个计算旧的工资所得税,一个计算新的工资所得税。 下面的函数old_tax用来计算旧的所得税 import sys import bisect def old_tax(salary): if salary < 3500 : return 0.0 above = salary - 3500 ranges = [ 0 , 1500 , 4500 , 9000 , 35000 ,
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS8安装Docker,最新的服务器搭配容器使用
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS关闭SELinux安全模块
- CentOS7设置SWAP分区,小内存服务器的救世主
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装