useEffect 的作用
useEffect 是 React Hooks 中用于处理副作用的钩子函数。副作用是指那些不直接与组件渲染相关,但需要在组件生命周期中执行的操作,例如数据获取、订阅事件、手动修改 DOM 等。
如何理解副作用
在 React 中,组件的核心逻辑是渲染 UI,但某些操作(如 API 调用、定时器、事件监听)会影响外部状态或执行非渲染相关的任务,这些操作被称为"副作用"。
useEffect 的基本用法
jsx
useEffect(() => {
// 副作用逻辑(如数据获取、订阅事件)
return () => {
// 清理逻辑(如取消订阅、清除定时器)
};
}, [dependencies]);
- 第一个参数(函数):定义副作用的执行逻辑。
- 第二个参数(依赖数组) :控制副作用何时重新执行。如果依赖项变化,副作用会重新运行;若为空数组
[],则仅在组件挂载和卸载时执行。 - 清理函数(return):在组件卸载或依赖项变化前执行清理操作(如取消订阅)。
常见用例
数据获取
jsx
useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
setData(data);
};
fetchData();
}, []); // 空数组表示仅在组件挂载时执行
事件监听
jsx
useEffect(() => {
const handleResize = () => console.log('Window resized');
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []); // 清理函数移除监听
依赖项控制
jsx
useEffect(() => {
console.log('Count updated:', count);
}, [count]); // 仅在 count 变化时执行
关键点
- 避免无限循环:确保依赖项正确,避免频繁触发副作用。
- 清理资源:防止内存泄漏(如定时器、订阅未清除)。
- 按需执行:通过依赖项优化性能,减少不必要的副作用调用。
具体实例解析:
以事件监听为实例,代码如下:
javascript
useEffect(() => {
const handleResize = () => console.log('Window resized');
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []); // 清理函数移除监听
运行顺序解析
-
组件挂载阶段
当组件首次渲染时,
useEffect的回调函数会立即执行。代码中的箭头函数() => { ... }被调用,完成以下操作:- 定义
handleResize函数。 - 调用
window.addEventListener('resize', handleResize)注册事件监听器。
- 定义
-
依赖数组的作用
依赖数组
[]表示该useEffect仅在组件挂载时执行一次。若依赖数组包含变量(如[someVar]),则变量变化时会重新执行回调函数及其清理函数。 -
清理函数执行时机
清理函数
return () => { ... }会在以下两种情况下执行:- 组件卸载时(如页面导航或组件被移除)。
- 依赖项变化导致
useEffect重新执行前(先执行清理函数,再运行新回调)。
具体流程示例
- 首次渲染 :
handleResize定义 →addEventListener调用 → 监听器生效。 - 重新渲染(依赖不变):无操作(因依赖数组为空,回调不会重复执行)。
- 组件卸载 :清理函数
removeEventListener被调用,移除监听器。
注意事项
- 清理函数的作用是避免内存泄漏,确保监听器随组件生命周期正确解除绑定。
- 若依赖数组非空,清理函数会在每次依赖变化时优先执行。