前言
React Hooks
已经出现在人们的视野里很久了, 不得不承认的是, 这是 React
开发团队未来的发展方向, 如果你是一个 函数式编程
的爱好者,你可能为之兴奋, 如果你是一个 面向对象编程
的爱好者, 那么…
要解救什么问题
很明显,这不是 一帮为了 KPI的程序员搞出来的东东, 也不是 这不是邓紫棋要帮你唱的 Hook.
React Hooks
要实现 状态逻辑复用
, 在这之前还有三种熟悉的方案
render props
1
2
3
4
5
6
7<CountDown>
{
(s)=> (
`还有 ${s} 秒`
)
}
</CountDown>HOC 高阶组件
1
2@B
class A extends React.Component{}远古时期的
mixins
方案 (废弃)
从最早的的 React.createClass
api .
再到 拥抱 ES6 的 class
再到 现在 抛弃 class
更加函数式编程的 React Hooks
React
团队一直提倡的是 视图与逻辑分离, 很遗憾这样去做的人很少
有状态的组件没有渲染,有渲染的组件没有状态
这是 对React Hooks的一些思考 这篇文章中提到的观点, 也是 React团队引入 React Hooks
的想要达到的
好处是啥?
- immutable
- 更纯粹的函数式编程
- 代码量更少
- 减少逻辑复用的嵌套层级
- 同步
这是一个计数的 demo, 显示点击了按钮多少次
class 版本
1 | class Counter extends React.Component { |
Hooks 的版本
1 | function Counter() { |
是的在 Class
版本中 this.state.count
每一次改变,会触发视图更新, this
是可变的
而在 Hooks
版本中 , count
仅仅是一个数字,
函数第一次执行
1 | function Counter() { |
点击按钮后函数第二次执行
1 | function Counter() { |
每一次值都独立于其他渲染, 不会随着时间改变
在这里你可能会问? 那么每次都是独立渲染, 那么如果疯狂点击 1000 次 那么会执行 1000 次函数 ?
是的, 你可以用 PureComponent
的函数式版本 React.memo
来优化重复渲染
1 | function Counter() { |
生命周期咋整?
componentDidMount
componentWillReceiveProps
componentWillUnmount
这些都被吃了吗? 是的 都被吃了 , 吐出了一个 useEffect
Hooks 给你
在上面的计数例子中
1 | componentDidUpdate() { |
在之前讲到了 由于 this 是可变的, 在点击 比如5
次 之后, 一共打印了 5 次
1 | 你点击了 5 次 (打印了 5 次) |
而在 Hooks
的版本中, 由于当前渲染的 count
独立于其他渲染 (可以理解成闭包)
1 | function Counter() { |
那么得到的结果是
1 | 你点击了 1 次 |
useEffect(fn,[...args])
有两个参数 ,第二个参数是一个数组,数组里面的值发生改变才会重新执行
如果不传的话, 每次函数执行都会执行fn
如果是个空数组, 则表示只执行一次, 可以用来实现 componentDidMount
1 | function Counter() { |
想实现 componentDidMount
绑定一个事件, componentWillMount
取消绑定
1 | function Counter() { |
可以看到 useEffect
里面有一个 经典的 柯里化
组件卸载时 这会执行 它
对于另外一个经典的场景, 组件props
或 state
更新后 执行某一个函数 或者重新初始化一个东西, 相比看到这 你也懂了
1 | function Counter() { |
在这里 每次 count
更新后 就会重新执行 someFn()
当然 React
还提供了很多美味的 Hook
供我们品尝 更多的花样等着我们把玩
在这里可以抛出一些问题
- 为什么 Hook 都是以
use
开头, 有什么特殊含义吗? - 哪些生命周期还没有
hooks
的实现 class
组件 可以用在 hooks 里面吗?- 怎么才能写出合理的
hooks
呢? 有哪些我们需要遵守的约定呢? - 怎么实现 一些常用的 自定义
Hook
? - 项目上的实践分享?