React进阶系列之Why Hooks?

本篇我们来深入一个问题,Why React Hooks?
上一篇我们几乎花了通篇的文字阐述了 Hooks 的设计理念,最后的结论是 函数组件从设计思想上来看,更加契合 React 的理念,这可以作为上述问题的一个答案,除此之外,还有哪些理由可以作为我们去使用 React Hooks 的原因吗?
Why Hooks?
以 “Why xxx” 开头的问题,往往都没有标准答案,但会有一些关键的“点”,除了设计理念层面,还有以下原因,
- 告别难以理解的 Class
- 解决业务逻辑难以拆分的问题
- 使状态逻辑复用变得简单可行
接下来我们就上述三个点展开来看一下,Why Hooks?
告别难以理解的 Class:把握 Class 的两大痛点
类组件的两大痛点是什么?this和生命周期。
对于生命周期,大家应该都了解,经过三次版本的更迭,其中有不少学习和理解成本。我们重点来说说 this,以下面代码为例,我们不用关心组件具体的逻辑,就看 changeText 这个方法:它是 button 按钮的事件监听函数。当我点击 button 按钮时,希望它能够帮我修改状态,但事实是,点击发生后,程序会报错。原因很简单,changeText 里并不能拿到组件实例的 this。
class Example extends Component {
state = {
text: ""
};
changeText() {
// 这里会报错
this.setState({ text: 'Hello'});
}
render() {
return <button onClick={this.changeText}>{this.state.text}</button>
}
}
为了解决 this 不符合预期的问题,前端几乎也是各显神通,之前用 bind、现在推崇箭头函数。但不管什么招数, 本质上都是在用实践层面的约束来解决设计层面的问题。而 Hooks 基于函数组件,我们不需要关心 this,因为根本就没有 this,这在心智层面和理解上无疑是优于类组件的。
解决业务逻辑难以拆分的问题:Hooks可以实现更好的逻辑拆分
回忆一下在过去,我们是如何组织业务逻辑的?多数情况下应该都是先想清楚业务的需求是什么样的,然后将对应的业务逻辑拆分到不同的生命周期函数里面去,这意味着什么呢?意味着逻辑与生命周期耦合在一起了。
在这样的前提下,我们发现生命周期函数往往背离了单一职责原则,一个生命周期函数里面往往需要做不只一件事,在稍复杂的 React 应用里,它们的体积往往很庞大,内部的逻辑也异常复杂,给阅读和维护带来很多麻烦,比如下面这个例子,
class Example extends Component {
componentDidMount() {
// 1. 这里发起异步调用
// 2. 这里从 props 里获取某个数据,根据这个数据更新 DOM
// 3. 这里设置一个订阅
// ...
}
componentWillUnMount() {
// 在这里卸载订阅
}
componentDidUpdate() {
// 1. 在这里根据 DidMount 获取到的异步数据更新 DOM
// 2. 这里从 props 里获取某个数据,根据这个数据更新 DOM
}
}
这些事情之间看上去毫无关联,逻辑就像是被“打散”进生命周期里了一样 。比如,设置订阅和卸载订阅的逻辑,虽然它们在逻辑上是有强关联的,但是却只能被分散到不同的生命周期函数里去处理,这无论如何也不能算作是一个非常合理的设计。
而在 Hooks 的帮助下,我们完全可以把这些繁杂的操作 按照逻辑上的关联拆分进不同的函数组件里: 我们可以有专门管理订阅的函数组件、专门处理 DOM 的函数组件、专门获取数据的函数组件等。Hooks 能够帮助我们 实现业务逻辑的聚合,避免复杂的组件和冗余的代码 。
Hooks使状态逻辑复用变得简单可行
React 在原生层面并没有为我们提供状态逻辑复用的姿势,所以在过去,我们靠的是 HOC(高阶组件)和 Render Props 这些组件设计模式,但这些设计模式并非万能,它们在实现逻辑复用的同时,也破坏着组件的结构,其中一个最常见的问题就是“嵌套地狱”现象。
而 Hooks 可以看作 React 为解决状态逻辑复用这个问题所提供的一个原生途径,现在我们可以通过自定义 Hooks 来解决状态复用的问题。
保持清醒:Hooks 并非万能
尽管 Hooks 有千般好,我们仍要保持清醒,认识到它的一些局限性,主要有以下几点,
- Hooks 暂时还不能完全地为函数组件补齐类组件的能力 :比如 getSnapshotBeforeUpdate、componentDidCatch
- “轻量”几乎是函数组件的基因,这可能会使它不能够很好地消化“复杂” :如果用函数组件来解决复杂的业务问题,逻辑的拆分和组织会是一个很大的挑战,耦合和内聚的边界,有时候真的很难把握, 函数组件给了我们一定程度的自由,却也对开发者的水平提出了更高的要求
- Hooks 在使用层面有着严格的规则约束:如果不能牢记并践行 Hooks 的使用原则,对 Hooks 的关键原理没有扎实的把握,很容易把自己的 React 项目搞成大型车祸现场
相关文章
写在最后
本文首发于我的 博客,才疏学浅,难免有错误,文章有误之处还望不吝指正!
如果有疑问或者发现错误,可以在评论区进行提问和勘误,
如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。