useEffect
是 React 中的一个基础 Hook,允许你在函数组件中执行副作用(side effects)。副作用指的是那些影响组件外部系统或环境的操作,比如数据获取、手动 DOM 操作、订阅事件、定时器等。
1. useEffect
的基本概念
- 副作用:在 React 组件的渲染过程中,除了返回 UI 结构外,可能还需要执行一些与 UI 渲染无关的操作,这些操作称为副作用。例如,API 请求、修改 DOM、订阅 WebSocket 等。
- useEffect:这个 Hook 是为了解决在函数组件中处理副作用的需求。它的作用类似于类组件中的
componentDidMount
、componentDidUpdate
和componentWillUnmount
生命周期钩子。
2. 基础使用
useEffect
的基本语法是:
useEffect(() => {
// 这里写副作用的逻辑
return () => {
// 可选的清理函数
};
}, [依赖项]);
- 第一个参数:是一个回调函数,表示副作用的具体逻辑。
- 第二个参数:是一个依赖项数组,决定了副作用何时执行。
示例:简单的数据获取
import React, { useState, useEffect } from 'react';
function DataFetchingComponent() {
const [data, setData] = useState(null);
useEffect(() => {
// 执行副作用:数据请求
fetch('https://api.example.com/data')
.then((response) => response.json())
.then((result) => setData(result));
}, []); // 空数组表示副作用只在组件首次渲染时执行
return (
<div>
<h1>数据获取</h1>
{data ? <pre>{JSON.stringify(data, null, 2)}</pre> : <p>加载中...</p>}
</div>
);
}
export default DataFetchingComponent;
3. useEffect
的三种使用方式
3.1 没有依赖项
如果不提供依赖项数组,useEffect
在每次组件渲染时都会执行。
useEffect(() => {
console.log('每次组件渲染都会执行');
});
这种情况适用于那些需要在每次渲染时都执行的副作用操作,比如日志输出或 DOM 操作。
3.2 空依赖项数组
如果依赖项数组为空 []
,useEffect
只会在组件首次渲染时执行一次,类似于类组件中的 componentDidMount
。
useEffect(() => {
console.log('仅在组件首次渲染时执行');
}, []);
这种情况适用于只需要在组件初始化时运行的副作用,比如 API 请求、订阅事件等。
3.3 有依赖项的情况
你可以将一个或多个状态或 props 作为依赖项传递给 useEffect
,当这些依赖项的值发生变化时,副作用才会重新执行。
useEffect(() => {
console.log('当 count 变化时执行');
}, [count]); // 只有 count 变化时,副作用才会重新执行
这种情况适用于需要根据某些条件更新的副作用,比如根据用户输入进行数据过滤或重新获取数据。
4. 清理副作用
有时,副作用可能会引入一些资源(例如订阅、定时器、WebSocket 连接等),我们需要在组件卸载或副作用更新时进行清理。这可以通过 useEffect
的返回值来实现。
示例:设置和清除定时器
import React, { useState, useEffect } from 'react';
function TimerComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setCount((prevCount) => prevCount + 1);
}, 1000);
// 返回一个函数,清除定时器
return () => {
clearInterval(timer);
};
}, []); // 空依赖数组,表示副作用仅在组件挂载时执行一次
return <h1>计数: {count}</h1>;
}
export default TimerComponent;
在这个示例中,setInterval
设置了一个定时器,我们通过 useEffect
的返回函数在组件卸载时清除这个定时器,避免内存泄漏。
5. 常见用途
- 数据获取:从服务器或 API 获取数据,并在组件中渲染。
- 订阅:订阅某些全局事件,如 WebSocket 连接或外部库的事件。
- 手动 DOM 操作:在组件渲染后直接操控 DOM 元素。
- 定时操作:设置定时器或轮询数据。
6. useEffect
的注意事项
- 避免不必要的副作用:将依赖项数组正确设置为副作用需要的变量,避免每次渲染时都执行不必要的操作。
- 防止内存泄漏:对于需要清理的副作用(如定时器、事件监听器等),一定要在
useEffect
的返回函数中清理它们。 - 不要在
useEffect
中直接更新状态:如果副作用更新状态且导致组件重新渲染,要小心不要引发无限循环。
总结
useEffect
是 React 函数组件中处理副作用的核心工具,通过正确使用它,你可以在组件生命周期的不同阶段执行副作用,比如获取数据、订阅事件、手动操作 DOM 等。如果你需要在某些特定时机执行代码(如首次加载或依赖变化时),useEffect
就是你需要的工具。