第一遍学hook的时候,只是匆匆带过了几种hook的使用,也用useState、useEffect写了一个小demo
但是在看项目代码的时候,发现了effecthook之前没学到的东西,遂回头再学一次,加深理解并记录下来。
1、定义
Effect Hook 可以让你在函数组件中执行副作用操作,数据获取,设置订阅以及手动更改 React 组件中的 DOM 都属于副作用。不管你知不知道这些操作,或是“副作用”这个名字,应该都在组件中使用过它们。
2、使用
2.1 初次理解
effect hook 一定程度上充当了在函数组件中生命周期的作用,官方文档都让我们把 useEffect 想象成 componentDidMount, componentDidUpdate,componentWillUnmount 三个生命周期的结合体。
(这也造成了我对effect hook理解的误区,具体后面会有介绍。)
官网给出的例子是这样使用effect hook的
用来取代如下的class组件生命周期
很容易得出结论:effect hook 在挂载(初始化)和每次更新时都会调用,正好代替了componentDidMount, componentDidUpdate两个过程。
(最初的我也是这样理解的,单纯的以为useEffect只能这么用)
但在第二次学习effect hook时,我才知道useEffect的第二个参数:
2.2 二次学习的补充——3种使用场景
a、挂载和更新时调用
当useEffect没有第二个参数时,组件的初始化和更新都会执行。(也就是官网给的例子)
useEffect(() => {
console.log('hello world')
});
b、仅挂载时调用:
useEffect的第二个参数为一个空数组,初始化调用一次之后不再执行,相当于componentDidMount。( [ ]依赖数组中为空,也就是数组中的值不会变,也就是永不更新)
useEffect(() => {
console.log('hello world')
}, [])
c、仅更新特定数据时调用:
可以给 useEffect 传递第二个参数,它是 effect 所依赖的值数组。只有参数数组中的值更新了,才进行调用。
useEffect(
() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
},[props.source],);
3、分类
官网给出的分类是:需要清除的effect 和 无需清除的effect
useEffect 的执行代码中可以返回一个函数,在每一次新的 render 进行前或者组件 unmount 之时,都会执行此函数,进行清理工作。
3.1 需要清除的effect
用return一个函数的方式代替 componentWillUnmount 生命周期
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
//unmount要做的事,清除操作
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
3.2 无需清除的effect
无需清除的effect则和2中例子一致,不需return返回值。
4、总结
-
每次初始化的时候必定执行一次。
-
如果返回了函数,那么在下一次 render 之前或组件 unmount 之前必定会运行一次返回函数的代码。
-
如果指定了依赖数组,且不为空,则当数组里的每个元素发生变化时,都会重新运行一次。
-
如果数组为空,则只在第一次 render 时执行一次,如果有返回值,则同 3。
-
如果在 useEffect 中更新了 state,且没有指定依赖数组,或 state 存在于依赖数组中,就会造成死循环。