一、Hooks概念及意义
什么是Hooks?
之前在react中,组件都是用class的形式来编写的,只有无状态组件才可以用function形式编写的。Hooks 允许我们在组件中使用特定的预定义内部函数 来标记状态和组件生命周期,使得所有组件都可以用函数来编写。
使用类组件的缺点:
-
难以复用的状态逻辑
在Hooks出现之前,是通过渲染属性和高阶组件实现。 渲染属性 是指用一个函数组件的执行结果来当做自己的渲染结果,相当于Foo组件进入到了Resizeable组件的内部,拿到了其内部变量size。 高阶组件 此时resizeable不再是一个组件,而是一个函数。这个函数动态创建了一个类组件,这个函数有两个任务,一是维护size状态,二是渲染resizeable的第一个组件参数 即Foo。 然而,无论是渲染属性还是高阶组件,都增加了原有组件的渲染层级,导致层级冗余。
-
难以捉摸的生命周期
相干的逻辑分散在不同的生命周期中,而每个生命周期还会混杂不相干的逻辑。这样混乱的写法,容易产生bug,且不易拆分代码。
-
this指向困扰
没听懂??
Hooks的意义?
- 函数组件无this问题
- 自定义Hook方便复用状态逻辑
- 副作用的关注点分离
副作用:除了数据到视图层渲染之外的操作,都是副作用,比如异步发起网络请求,获取dom,事件监听和事件解绑等。useEffect()是渲染之后运行,很适合完成副作用。
二、使用State Hooks
所有的Hook,包括自定义的都得用 “use” 开头。
useState
该方法返回一个 只有两个成员 的数组,第一个成员是state中数据的名称,第二个成员是设置该数据的方法名称。
useState是按照第一次执行的顺序,来返回特定的state的。
useState必须定义在顶层,不能放在条件语句和循环语句中,因为useState的数量在每一次渲染中,必须是一样的,不能多也不能少。
通过eslint-plugin-react-hooks来帮助我们做校验。
安装:
npm i eslint-plugin-react-hooks -D
配置:
useState例子:
不使用Hook时:
使用Hook时:
总结:useState 必须按照固定的顺序和数量被调用,而且可以传入一个参数当做这个状态的默认值,既然是默认值,那么在不同的渲染周期去传入不同的值是没有意义的
,只有第一次传入才有效。
三、使用Effect Hooks
副作用 包含:
- 绑定事件
- 网络请求
- 访问DOM
副作用时机:
- Mount 之后 => componentDidMount()
- Update 之后 => componentDidUpdate()
- Unmount 之前 => componentWillUnmout()
useEffect可以覆盖上述所有的情况。
不使用useEffect时:
使用useEffect时:
useEffect第一参数是要执行的逻辑,第二个参数是这段逻辑所依赖的参数组成的数组,是可选的,只要数组的某一项发生改变时,useEffect就会执行。
useEffect不传第二个参数时,相当于componentDidUpdate(),每一次页面渲染就会执行。useEffect第二个参数为空数组[]时,相当于componentDidMount(),只会执行一次。
通过这个例子可以感受到useEffect的优势:一个是提高了代码复用,一个是副作用关注点分离。
四、使用Context Hooks
使用consumer:
使用contextType:
使用useContext:
五、使用Memo/Callback Hooks
useMemo和Memo
Memo函数针对的是一个组件的渲染是否重复执行,而useMemo则针对的是一段函数逻辑是否重复执行。两者的本质都是使用一样的算法来判断依赖是否发生改变,继而决定是否触发特定逻辑。都是只用来做性能优化。
useMemo和useEffect
useMemo使用的形式和useEffect一样,但不同的是useMemo第二个参数是必传的,否则useMemo每次都会执行,就不是shouldComponentUpdate()生命周期函数了。
useMemo和useEffect还有一点不同是,useEffect是渲染后执行的,而useMemo是在渲染中执行的,它可以参与到渲染中。
useMemo和useCallback
useMemo(()=>fn)
等价于
useCallback(fn)
useCallback是useMemo的一种变形。
六、使用Ref Hooks
使用场景:
- 获取子组件或者DOM节点的句柄;
- 渲染周期之间共享数据的存储;