前期准备
要把 react
和 react-dom
更新到 16.7.0-alpha
及以上,如果配置了 ESLint,记得添加对应的 Plugin。
(安装插件能够帮助你不弄错每个盒子和状态的对应关系,书写的时候 Hooks 需要 use
开头且放在顶层作用域,即不可以包裹 if/switch/when/try
等)
React Hooks 的本质
Hooks 本质是把面向生命周期编程变成了面向业务逻辑编程;
Hooks 使用上是一个逻辑状态盒子,输入输出表示的是一种联系;
Hooks 是 React 的未来,但还是无法完全替代原始的 Class。
业务逻辑复用
这里说的业务逻辑复用主要是需要跨生命周期的业务逻辑。单单按照组件堆积的形式组织代码虽然也可以达到各种复用的目的,但是会导致组件非常复杂,数据流也会很乱。组件堆积适合 UI 布局,但是不适合逻辑组织。为了解决这些问题,在 React 发展过程中,产生了很多解决方案,
Mixins
坏处远远大于带来的好处,因为现在已经不再支持,不多说,可以看看这篇文章:Mixins Considered Harmful。
Class Inheritance
官方 很不推荐此做法
High-Order Components (HOC)
React 高阶组件 在封装业务组件上简直是屡试不爽,它的实现是把自己作为一个函数,接受一个组件,再返回一个组件,这样它可以统一处理掉一些业务逻辑并达到复用目的。
比较常见的一个就是 react-redux
里的 connect
函数:
但是在调试的时候可以看到会产生“组件嵌套地狱”
Render Props
Render Props 其实很常见,比如 React Context API:
class App extends React.Component {
render() {
return (
<ThemeProvider>
<ThemeContext.Consumer>
{val => <div>{val}</div>}
</ThemeContext.Consumer>
</ThemeProvider>
)
}
}
它的实现思路很简单,把原来该放「组件」的地方,换成了回调,这样当前组件里就可以拿到子组件的状态并使用。
但是,同样这会产生 Wrapper Hell 问题:
状态盒子
Hooks 只能在其它 Hooks 的函数或者 React Function 组件里。
React 社区一直推崇函数式、纯函数等思想,引入 Hooks 概念后的 Functional Component
变的不再纯了,useXxx
与其说是一条执行语句,不如说是一个声明。声明这里放了一个「状态盒子」,盒子有输入和输出,剩下的内部实现就一无所知,重要的是,盒子是有记忆的,下次执行到此位置时,它有之前上下文信息。
类比「代码」和「程序」的区别,前者是死的,后者是活的。表达式 c = a + b
表示把 a
和 b
累加后的值赋值给 c
,但是如果写成 c := a + b
就表示 c
的值由 a
和 b
相加得到。看起来表述差不多,但实际上,后者隐藏着一个时间的维度,它表示的是一种联系,而不单单是个运算。这在 RxJS 等库中被大量使用。
这种声明目前是通过很弱的 use
前缀标识的(但是设计上会简洁很多),为了不弄错每个盒子和状态的对应关系,书写的时候 Hooks 需要 use
开头且放在顶层作用域,即不可以包裹 if/switch/when/try
等。如果你按文章开头引入了那个 ESLint Plugin 就不用担心会弄错了。
Fragment
Wrapper Hell,我个人觉得使用 Fragment 也可以基本解决。
案例讲解
功能需求
根据 input 的输入值更改网页的 title 信息
Class Component
import React from 'react'
class ChangeTile extends React.Component {
constructor(props) {
super(props)
this.state = {
title = ''
}
}
handleChage(title) {
this.setState({
title
})
}
render() {
return (
<div>
<input value={this.state.title} onChange={this.handleChage(title)} />
</div>
)
}
}
Hooks 写法
后记
HOC 和 Render Props 还是有存在的必要,一方面是支持 React Class,另一方面,它们不光适用于纯逻辑封装,很多时候也适合逻辑 + 组件的封装场景,虽然此时使用 Hooks 也可以,但是会显得啰嗦点。
参考资源
官网文档
Making Sense of React Hooks
https://www.yuque.com/es2049/blog