useEffect是React Hook的一种,用于在函数组件中定义副作用操作,比如改变DOM、发送网络请求、订阅事件等等。useEffect用于替代类组件中的生命周期方法。它接受一个函数作为第一个参数,在组件更新时调用这个函数,如果你需要在组件挂载时调用这个函数,需要传入一个空数组作为第二个参数;如果需要更新时再次调用这个函数,则不传数组或者传入一些依赖变量。
useEffect可以执行异步操作,并且还可以返回一个函数用于清理操作。例如,在组件挂载时,你可能需要订阅一些事件,在组件卸载时就需要取消订阅,可以在useEffect中返回一个取消订阅函数。
比如这个例子,假设我们有一个组件,需要在显示时向后端发送网络请求,获取数据后渲染该组件:
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function MyComponent() {
const [data, setData] = useState([]);
useEffect(() => {
const fetchData = async () => {
const result = await axios.get('/api/data');
setData(result.data);
}
fetchData();
}, []);
return (
<div>
{data.map((item) => <div key={item.id}>{item.name}</div>)}
</div>
);
}
export default MyComponent;
在这个例子中,我们传入了一个空数组[]作为第二个参数到useEffect中,表示只在组件挂载时执行里面的函数,不会在之后的更新中再次执行。
这个例子中,我们在组件挂载后立即执行发起网络请求的函数,并把请求结果存储在state中,并通过map方法渲染数据。当组件挂载时,useEffect中的函数被调用,发出网络请求,得到结果后将数据存储在state中。当state更新时,组件重新渲染,并展示最新的结果。
如果我们不传第二个参数或传入一些依赖变量,那么组件每次更新都会重新执行useEffect中的函数。
再举个例子:
假设我们有一个需求:在页面中显示一个计数器,每隔1秒更新一次。我们可以使用useState Hook存储计数器的值,使用useEffect Hook实现定时更新。
import React, { useState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const intervalId = setInterval(() => {
setCount(count => count + 1);
}, 1000);
// 返回一个清除定时器的函数
return () => clearInterval(intervalId);
}, [count]);
return (
<div>
<p>The counter is: {count}</p>
</div>
);
}
export default Counter;
这里我们在useEffect的第二个参数传入了[count],这样每次更新count的值后都会重新调用useEffect,如果传的是空数组的话,useEffect就只会在挂载的时候调用。
需要注意的是,当useEffect的第二个参数为空数组时,useEffect函数中使用到的state、props、context等值不会及时更新,这些值仅在组件初次挂载时被记录下来。如果需要在组件状态变化时执行一些副作用操作,应该将组件状态作为useEffect的依赖项传入,以确保useEffect能够响应状态变化。
return () => clearInterval(intervalId);这个清除函数会在组件卸载或者每次更新前的时候调用。