前言
React Hooks 已经出现在人们的视野里很久了,不得不承认的是,这是 React 开发团队未来的发展方向,如果你是一个 函数式编程 的爱好者,你可能为之兴奋,如果你是一个 面向对象编程的爱好者,那么。..
要解救什么问题
很明显,这不是 一帮为了 KPI 的程序员搞出来的东东,也不是 这不是邓紫棋要帮你唱的 Hook.
React Hooks 要实现 状态逻辑复用, 在这之前还有三种熟悉的方案
render props1
<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() { |
生命周期咋整?
componentDidMountcomponentWillReceivePropscomponentWillUnmount
这些都被吃了吗?是的 都被吃了 , 吐出了一个 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? - 项目上的实践分享?
