01 React Hook 简介
首先,欢迎你来学习React Hook,通过本教程你会了解到React Hook工作原理以及我们推荐使用Hook的理由。
学习前提
在学习本课程之前,需要你对以下知识点有基础的了解:
1、React基础原理;
2、函数组件(Functional components)和类组件(class components),属性传参(props),自定义内部数据(state),生命周期函数等;
3、使用谷歌浏览器且安装了“React Developer Tools”调试工具。
本系列文章适合有一定React开发基础的人,若是React新手,建议先从阅读React官方中文文档学起。
接下来正式开始本教程。
什么是Hooks?
Hook是React 16.8版本中新增的一个新特性,丰富扩展了原有函数组件的功能,让函数组件拥有了像类组件一样的相似特性。
在之前版本中函数组件不能使用React生命周期函数,Hook本身单词意思是“钩子”,作用就是“勾住某些生命周期函数或某些数据状态,并进行某些关联触发调用”。
不同的Hook(钩子)有不同的作用,可以勾住不同的“点”,比如“勾住组件更新完成对应的生命周期函数”、“勾住某props值的变化”等。
正因为React有多个内置Hook,所以本小节的标题才是“什么是Hooks?”,没错,用到了Hook的复数单词Hooks。
特别提醒:在React官网中使用的是Hook,而在有些教程中使用的 是Hooks。在本教程中Hook和Hooks是同一个意思,不要纠结什么时候用单数什么时候是复数
请注意
1、尽管函数组件拥有了类组件多大多数的相似特性,但有一点除外:函数组件中没有类组件中“自定义state”的特性,因此你无法在函数组件中使用“this.state.xx”这样的代码。
没有不代表功能的缺失,恰恰相反,因为当你充分了解Hooks之后,你会发现函数组件内部自定义数据状态功能远远超出类组件。
2、Hooks只能运行在函数组件中,不能运行在类组件中。
补充:准确来说,Hooks只能运行在函数组件的“内部顶层中”,不能运行在if/for等其他函数的代码体内,不允许被if/for等包裹住。
3、Hooks函数必须为纯函数,所谓纯函数就是函数内部不能修改可能影响执行结果的任意参数,确保每次执行的代码结果都是一样的。
为什么要用Hooks?
先说一下类组件的一些缺点:
缺点一:复杂且不容易理解的“this”
例如事件绑定处理函数,都需要bind(this)才可以正确执行。
例如想获取某些自定义属性,都需要使用this.state.xx或this.props.xx。
这样造成代码不够精简,并且有些时候热更新不能正常运行。
缺点二:组件数据状态逻辑不能重用、组件之间传值过程复杂
“组件数据状态逻辑不能重用”,详细解释如下:
“组件数据状态”是由:定义数据、默认赋值、获取数据、修改数据、数据逻辑几个环节构成。 由于类组件中的组件数据状态state必须写在该组件构造函数内部,无法将state抽离出组件,因此别的组件如果有类似state逻辑,也必须内部自己实现一次,所以才得出“组件数据状态逻辑不能重用”的结论。
“组件之间传值过程复杂”,详细解释如下:
React本身为单向数据流,即父组件可以传值给子组件,但子组件不允许直接修改父组件中的数据状态。
子组件为了达到修改父组件中的数据状态,通 常采用“高阶组件(HOC)”或“父组件暴露修改函数给子组件(render props)”这2种方式。 这2种方式都会让组件变得复杂且降低可复用性。
缺点三:复杂场景下代码难以组织在一起
复杂场景下,比如数据获取(data fetching)和事件订阅(event listeners),相关代码难以组织在一起。
“相关代码难以组织在一起”,详细解释如下:
第1个“难以组织”的原因:数据获取和事件订阅被分散在不同生命周期函数中。
例如数据获取:组件第一次被挂载(componentDidMount)、组件每次更新完毕(componentDidUpdate)
例如事件监听:组件第一次被挂载(componentDidMount)、组件即将被卸载(componentWillUnmount)
第2个“难以组织”的原因:内部state数据只能是整体,无法被拆分更细致
类组件中所有内部数据都被储存在this.state中,例如某个组件定义有2个内部数据 name,age,那么永远都是this.state.name、this.state.age。 name和age永远都只是this.state中的一个属性,无法做到将name和age拆分成独立对象个体。
所有内部数据都储存在this.state中,当内部数据复杂时,势必增加维护this.state的难度和复杂性。
“复杂场景下代码难以组织在一起”会造成另外一个延伸性问题:加大了代码自动测试难度。