React useEffect 使用指南
2023-09-13 08:09:36
React useEffect 是一个内置的 React hook,用于处理组件副作用。副作用是指组件在更新后会执行的任何操作,例如:
- 在 DOM 中修改元素
- 发起网络请求
- 设置定时器
- 更新存储在 state 之外的变量
useEffect 允许您在组件生命周期的特定时刻执行这些操作。它有以下几个主要特点:
- useEffect 是一个声明周期钩子(lifecycle hook)。这意味着它会在组件的不同生命周期阶段调用。
- useEffect 接受两个参数:一个回调函数和一个依赖项数组。
- 回调函数会在组件渲染后立即调用。如果组件被重新渲染,回调函数也会再次调用。
- 依赖项数组指定了回调函数何时应该被调用。如果依赖项数组中的任何值发生改变,回调函数就会再次调用。
useEffect 有许多常见用例,包括:
- 发起网络请求:可以使用 useEffect 来发起网络请求,并在请求成功后更新组件的 state。
- 设置定时器:可以使用 useEffect 来设置定时器,并在定时器触发时更新组件的 state。
- 更新存储在 state 之外的变量:可以使用 useEffect 来更新存储在 state 之外的变量,例如:refs 或 context。
useEffect 是一个非常强大的钩子,可以用来处理各种各样的组件副作用。掌握 useEffect 的使用可以帮助您编写更具响应性、更易维护的 React 应用程序。
useEffect 的调用时机
useEffect 会在组件渲染后立即调用。如果组件被重新渲染,useEffect 也会再次调用。
useEffect 有两个调用时机:
- 初始渲染: 当组件首次渲染时,useEffect 会在组件渲染后立即调用。
- 状态更新: 当组件的状态发生改变时,useEffect 会在组件重新渲染后调用。
useEffect 的调用时机与组件的生命周期密切相关。组件的生命周期分为四个阶段:
- 挂载: 当组件首次被渲染到 DOM 中时,组件会进入挂载阶段。
- 更新: 当组件的状态或属性发生改变时,组件会进入更新阶段。
- 卸载: 当组件从 DOM 中移除时,组件会进入卸载阶段。
- 错误处理: 当组件在挂载或更新过程中遇到错误时,组件会进入错误处理阶段。
useEffect 会在组件的挂载和更新阶段调用。当组件首次渲染时,useEffect 会在组件渲染后立即调用。当组件的状态或属性发生改变时,useEffect 会在组件重新渲染后调用。
useEffect 的用法
useEffect 的用法非常简单。它接受两个参数:一个回调函数和一个依赖项数组。
回调函数会在组件渲染后立即调用。如果组件被重新渲染,回调函数也会再次调用。
依赖项数组指定了回调函数何时应该被调用。如果依赖项数组中的任何值发生改变,回调函数就会再次调用。
以下是一个简单的 useEffect 示例:
import React, { useEffect } from 'react';
function MyComponent() {
useEffect(() => {
// 这段代码会在组件渲染后立即执行
}, []);
return (
<div>
<h1>My Component</h1>
</div>
);
}
export default MyComponent;
在这个示例中,useEffect 会在组件渲染后立即调用。因为依赖项数组为空,所以回调函数不会再次调用。
如果我们要在组件的状态发生改变时调用回调函数,我们可以将 state 添加到依赖项数组中:
import React, { useEffect, useState } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
// 这段代码会在组件渲染后立即执行,并且会在 count 发生改变时再次执行
}, [count]);
return (
<div>
<h1>My Component</h1>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default MyComponent;
在这个示例中,useEffect 会在组件渲染后立即调用。当 count 发生改变时,useEffect 会再次调用。
useEffect 的常见用例
useEffect 有许多常见用例,包括:
- 发起网络请求:可以使用 useEffect 来发起网络请求,并在请求成功后更新组件的 state。
- 设置定时器:可以使用 useEffect 来设置定时器,并在定时器触发时更新组件的 state。
- 更新存储在 state 之外的变量:可以使用 useEffect 来更新存储在 state 之外的变量,例如:refs 或 context。
- 清理资源:可以使用 useEffect 来清理资源,例如:定时器、网络请求或 DOM 事件监听器。
以下是一些具体的示例:
- 发起网络请求:
import React, { useEffect, useState } from 'react';
function MyComponent() {
const [data, setData] = useState([]);
useEffect(() => {
fetch('https://example.com/api/data')
.then(response => response.json())
.then(data => setData(data));
}, []);
return (
<div>
<h1>My Component</h1>
<ul>
{data.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
</div>
);
}
export default MyComponent;
在这个示例中,useEffect 会在组件渲染后立即调用。它会发起一个网络请求,并在请求成功后更新组件的 state。
- 设置定时器:
import React, { useEffect, useState } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setCount(count + 1);
}, 1000);
return () => {
clearInterval(interval);
};
}, []);
return (
<div>
<h1>My Component</h1>
<p>Count: {count}</p>
</div>
);
}
export default MyComponent;
在这个示例中,useEffect 会在组件渲染后立即调用。它会设置一个定时器,每隔 1 秒钟就会更新组件的 state。
- 更新存储在 state 之外的变量:
import React, { useEffect, useRef } from 'react';
function MyComponent() {
const ref = useRef(null);
useEffect(() => {
ref.current.focus();
}, []);
return (
<div>
<h1>My Component</h1>
<input ref={ref} />
</div>
);
}
export default MyComponent;
在这个示例中,useEffect 会在组件渲染后立即调用。它会将 ref.current 设置为输入元素,然后将焦点设置到输入元素上。
- 清理资源:
import React, { useEffect } from 'react';
function MyComponent() {
useEffect(() => {
const eventListener = window.addEventListener('resize', () => {
// 做一些事情
});
return () => {
window.removeEventListener('resize', eventListener);
};
}, []);
return (
<div>
<h1>My Component</h1>
</div>
);
}
export default MyComponent;
在这个示例中,useEffect 会在组件渲染后立即调用。它会添加一个事件监听器,并在组件卸载时将其移除。