useEffect:执行副作用
useEffect,顾名思义,用于执行一段副作用。
通常来说,副作用是指一段和当前执行结果的无关的代码。
useEffect的具体用法:useEffect(callback, dependencies);
第一个为执行的函数callback,第二个是可选的依赖项数组dependencies。其中依赖项是可选的,如果不指定,那么callback就会在每次函数组件执行完后都执行;如果指定了,那么只有依赖项中的值发生变化的时候,它才会执行。
注意的是:useEffect是每个组件render完后判断依赖并执行的。
import React, {
useState,
useEffect
} from "react";
function BlogView({id}) {
// 设置一个本地 state 用于保存 blog 内容
const [blogContent, setBlogContent] = useState(null);
useEffect(() => {
// useEffect 的 callback 要避免直接的 async 函数,需要封装一下
const doAsync = async () => {
// 当 id 发生变化时,将当前内容清楚以保持一致性
setBlogContent(null);
// 发起请求获取数据
const res = await fetch(`/blog-content/${id}`);
// 将获取的数据放入 state
setBlogContent(await res.text());
};
doAsync();
}, [id]); // 使用 id 作为依赖项,变化时则执行副作用
// 如果没有 blogContent 则认为是在 loading 状态
const isLoading = !blogContent;
return (
<div> {isLoading ? "Loading..." : blogContent} </div>
)
}
export default BlogView();
useEffect还有两个特殊的用法:没有依赖项,以及依赖项作为空数组。
- 没有依赖项,则每次render后都会重新执行。例如:
useEffect(() => {
//每次render完一定执行
console.log('re-rendered');
})
- 空数组作为依赖项,则只在首次执行时触发,对应到Class组件就是componentDidMount。例如:
useEffect(() => {
//组件首次渲染时执行,等价于class组件中的componentDidMount
console.log('re-rendered');
}, [])
除了这些机制之外,useEffect还允许你返回一个函数,用于在组件销毁的时候做一些清理的操作。比如移除事件的监听。这个机制等价于类组件中的componentWillUnmount。举个例子,在组件中,我们需要监听窗口的大小变化,以便做一些布局上的调整:
// 设置一个 size 的 state 用于保存当前窗口尺寸
const [size, setSize] = useState({});
useEffect(() => {
// 窗口大小变化事件处理函数
const handler = () => {
setSize(getSize());
};
// 监听 resize 事件
window.addEventListener('resize', handler);
// 返回一个 callback 在组件销毁时调用
return () => {
// 移除 resize 事件
window.removeEventListener('resize', handler);
};
}, []);
总结一下,useEffect让我们能够在下面四种时
机去执行一个回调函数产生副作用:
- 每次render后执行:不提供第二个依赖项参
数。比如useEffect(() => {})。 - 仅第一次render后执行:提供一个空数组作
为依赖项。比如useEffect((0)=>{},[])。 - 第一次以及依赖项发生变化后执行:提供依
赖项数组。比如useEffect(() => {}, [deps])。 - 组件unmount后执行:返回一个回调函数。比如useEffect(() =>{return() => {}},[])。