useEffect 钩子
介绍
在 React 中,useEffect
是一个非常重要的钩子(Hook),它允许你在函数组件中执行副作用操作。副作用是指那些与组件渲染无关的操作,例如数据获取、订阅、手动更改 DOM 等。useEffect
可以帮助你在组件渲染后执行这些操作,并且可以控制这些操作的执行时机。
基本用法
useEffect
的基本语法如下:
useEffect(() => {
// 在这里执行副作用操作
return () => {
// 清理操作(可选)
};
}, [dependencies]);
- 第一个参数:一个函数,包含你想要执行的副作用代码。
- 第二个参数(可选):一个依赖数组,用于控制副作用的执行时机。如果依赖数组中的值发生变化,副作用函数会重新执行。如果省略依赖数组,副作用函数会在每次组件渲染后执行。
示例 1:基本使用
import React, { useEffect, useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
在这个例子中,useEffect
会在 count
发生变化时更新文档标题。每次点击按钮时,count
会增加,从而触发 useEffect
中的副作用函数。
依赖数组的作用
依赖数组是 useEffect
的一个重要特性,它决定了副作用函数何时执行。以下是几种常见的使用方式:
- 空数组
[]
:副作用函数仅在组件挂载和卸载时执行一次。 - 包含依赖的数组
[dep1, dep2]
:当依赖数组中的任意一个值发生变化时,副作用函数会重新执行。 - 省略依赖数组:副作用函数会在每次组件渲染后执行。
示例 2:仅在挂载时执行
useEffect(() => {
console.log('Component mounted');
return () => {
console.log('Component unmounted');
};
}, []);
在这个例子中,副作用函数仅在组件挂载时执行一次,并在组件卸载时执行清理操作。
清理操作
在某些情况下,副作用函数可能需要执行一些清理操作,例如取消订阅或清除定时器。useEffect
允许你返回一个清理函数,这个函数会在组件卸载时或副作用函数重新执行之前调用。
示例 3:清理操作
useEffect(() => {
const timer = setInterval(() => {
console.log('Timer tick');
}, 1000);
return () => {
clearInterval(timer);
};
}, []);
在这个例子中,useEffect
设置了一个定时器,并在组件卸载时清除定时器。
实际应用场景
场景 1:数据获取
useEffect
常用于在组件挂载时获取数据。以下是一个简单的数据获取示例:
import React, { useEffect, useState } from 'react';
function DataFetching() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data));
}, []);
if (!data) {
return <div>Loading...</div>;
}
return (
<div>
<h1>Data:</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
在这个例子中,useEffect
在组件挂载时从 API 获取数据,并将数据存储在组件的状态中。
场景 2:订阅事件
useEffect
也可以用于订阅事件,例如窗口大小变化或键盘输入。
import React, { useEffect, useState } from 'react';
function WindowSize() {
const [size, setSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
useEffect(() => {
const handleResize = () => {
setSize({
width: window.innerWidth,
height: window.innerHeight,
});
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return (
<div>
<p>Width: {size.width}</p>
<p>Height: {size.height}</p>
</div>
);
}
在这个例子中,useEffect
订阅了窗口大小变化事件,并在组件卸载时取消订阅。
总结
useEffect
是 React 中处理副作用的强大工具。通过合理使用依赖数组和清理操作,你可以控制副作用的执行时机,并避免内存泄漏等问题。希望本文能帮助你理解 useEffect
的基本用法,并通过实际案例掌握其应用场景。
附加资源
练习
- 修改示例 1,使得文档标题在每次点击按钮时显示当前时间。
- 在示例 3 中,尝试添加一个按钮来手动清除定时器。
- 在场景 1 中,添加错误处理逻辑,以处理数据获取失败的情况。
在编写 useEffect
时,始终考虑是否需要清理操作,以避免潜在的内存泄漏问题。