背景
class时代,我们可以写class组件/函数式组件,两者的区别如下
| state | props | componentDidMounted | componentDidMounted | componentDidMounted | |
|---|---|---|---|---|---|
| class组件 | 有 | 有 | 有 | 有 | 有 |
| 函数组件 | 无 | 有 | 无 | 无 | 无 |
很明显,函数组件没有状态,没有什么周期,但是它有两个好处,不需要写constructor、不需要写this。
对于class组件的生命周期函数,componentDidMounted、componentDidMounted、componentDidMounted,对于一些实际的开发场景则不太适合,比如:
- 在挂载、更新时,需要根据新的props和state去更新dom元素,这样我们就需要在两个地方写同样的逻辑,逻辑分散了属于是。同时,如果我们在挂载期间写了这个逻辑,更新时却没有写,那就属于bug。
解决方案
hook主体分为
- 数据hook:useState、useContext、useReducer、useMemo、useCallBack
- 副作用hook:useEffect、useRef
在函数组件的基础上,我们通过hook可以将react的特性
钩入其中,而副作用hook就能很好的解决class组件的生命周期函数问题。
这样我们就实现了代码简洁,关联逻辑紧密贴合,减少无意义的bug。
hook的规则
- hook必须写在函数组件的顶层
- hook不能写在if、循环、嵌套中
- 自定义hook的名字必须以use开头
原理:函数组件内部会写多个hook,在初次渲染时,会将他们丢入hook队列,然后形成固定的队列顺序。然后在更新时,会拿这个队列去执行(这样才能知道代码中的useState、useEffect到底用的是state、effect里的哪一个),所以不能让初次渲染的hook队列和更新的hook队列不一致。