跳到主要内容

useEffect 钩子

介绍

在 React 中,useEffect 是一个非常重要的钩子(Hook),它允许你在函数组件中执行副作用操作。副作用是指那些与组件渲染无关的操作,例如数据获取、订阅、手动更改 DOM 等。useEffect 可以帮助你在组件渲染后执行这些操作,并且可以控制这些操作的执行时机。

基本用法

useEffect 的基本语法如下:

javascript
useEffect(() => {
// 在这里执行副作用操作

return () => {
// 清理操作(可选)
};
}, [dependencies]);
  • 第一个参数:一个函数,包含你想要执行的副作用代码。
  • 第二个参数(可选):一个依赖数组,用于控制副作用的执行时机。如果依赖数组中的值发生变化,副作用函数会重新执行。如果省略依赖数组,副作用函数会在每次组件渲染后执行。

示例 1:基本使用

javascript
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 的一个重要特性,它决定了副作用函数何时执行。以下是几种常见的使用方式:

  1. 空数组 []:副作用函数仅在组件挂载和卸载时执行一次。
  2. 包含依赖的数组 [dep1, dep2]:当依赖数组中的任意一个值发生变化时,副作用函数会重新执行。
  3. 省略依赖数组:副作用函数会在每次组件渲染后执行。

示例 2:仅在挂载时执行

javascript
useEffect(() => {
console.log('Component mounted');

return () => {
console.log('Component unmounted');
};
}, []);

在这个例子中,副作用函数仅在组件挂载时执行一次,并在组件卸载时执行清理操作。

清理操作

在某些情况下,副作用函数可能需要执行一些清理操作,例如取消订阅或清除定时器。useEffect 允许你返回一个清理函数,这个函数会在组件卸载时或副作用函数重新执行之前调用。

示例 3:清理操作

javascript
useEffect(() => {
const timer = setInterval(() => {
console.log('Timer tick');
}, 1000);

return () => {
clearInterval(timer);
};
}, []);

在这个例子中,useEffect 设置了一个定时器,并在组件卸载时清除定时器。

实际应用场景

场景 1:数据获取

useEffect 常用于在组件挂载时获取数据。以下是一个简单的数据获取示例:

javascript
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 也可以用于订阅事件,例如窗口大小变化或键盘输入。

javascript
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. 修改示例 1,使得文档标题在每次点击按钮时显示当前时间。
  2. 在示例 3 中,尝试添加一个按钮来手动清除定时器。
  3. 在场景 1 中,添加错误处理逻辑,以处理数据获取失败的情况。
提示

在编写 useEffect 时,始终考虑是否需要清理操作,以避免潜在的内存泄漏问题。