一个参数
useEffect()本身是一个函数,由 React 框架提供,在函数组件内部调用即可。
举例来说,我们希望组件加载以后,网页标题(document.title)会随之改变。那么,改变网页标题这个操作,就是组件的副效应,必须通过useEffect()来实现。
1import React, { useEffect } from 'react';
2
3function Welcome(props) {
4 useEffect(() => {
5 document.title = '加载完成';
6 });
7 return <h1>Hello, {props.name}</h1>;
8}
上面例子中,useEffect()的参数是一个函数,它就是所要完成的副效应(改变网页标题)。组件加载以后,React 就会执行这个函数。(查看运行结果)
useEffect()的作用就是指定一个副效应函数,组件每渲染一次,该函数就自动执行一次。组件首次在网页 DOM 加载后,副效应函数也会执行。
两个参数
有时候,我们不希望useEffect()每次渲染都执行,这时可以使用它的第二个参数,使用一个数组指定副效应函数的依赖项,只有依赖项发生变化,才会重新渲染。
1function Welcome(props) {
2 useEffect(() => {
3 document.title = `Hello, ${props.name}`;
4 }, [props.name]);
5 return <h1>Hello, {props.name}</h1>;
6}
上面例子中,useEffect()的第二个参数是一个数组,指定了第一个参数(副效应函数)的依赖项(props.name)。只有该变量发生变化时,副效应函数才会执行。
如果第二个参数是一个空数组,就表明副效应参数没有任何依赖项。因此,副效应函数这时只会在组件加载进入 DOM 后执行一次,后面组件重新渲染,就不会再次执行。这很合理,由于副效应不依赖任何变量,所以那些变量无论怎么变,副效应函数的执行结果都不会改变,所以运行一次就够了。
只运行一次
只需要在第二个参数传入空即可在页面加载后只执行一次
1function Welcome(props) {
2 useEffect(() => {
3 document.title = `Hello, ${props.name}`;
4 }, []);
5 return <h1>Hello, {props.name}</h1>;
6}
返回值
副效应是随着组件加载而发生的,那么组件卸载时,可能需要清理这些副效应。
useEffect()允许返回一个函数,在组件卸载时,执行该函数,清理副效应。如果不需要清理副效应,useEffect()就不用返回任何值。
1useEffect(() => {
2 const subscription = props.source.subscribe();
3 return () => {
4 subscription.unsubscribe();
5 };
6}, [props.source]);
上面例子中,useEffect()在组件加载时订阅了一个事件,并且返回一个清理函数,在组件卸载时取消订阅。
实际使用中,由于副效应函数默认是每次渲染都会执行,所以清理函数不仅会在组件卸载时执行一次,每次副效应函数重新执行之前,也会执行一次,用来清理上一次渲染的副效应。
注意
如果有多个副效应,应该调用多个useEffect(),而不应该合并写在一起。
1function App() {
2 const [varA, setVarA] = useState(0);
3 const [varB, setVarB] = useState(0);
4
5 useEffect(() => {
6 const timeout = setTimeout(() => setVarA(varA + 1), 1000);
7 return () => clearTimeout(timeout);
8 }, [varA]);
9
10 useEffect(() => {
11 const timeout = setTimeout(() => setVarB(varB + 2), 2000);
12
13 return () => clearTimeout(timeout);
14 }, [varB]);
15
16 return <span>{varA}, {varB}</span>;
17}
除另有声明外,本博客文章均采用 知识共享 (Creative Commons) 署名 4.0 国际许可协议 进行许可。转载请注明原作者与文章出处。