摘要:在本教程中,您将探索 React useEffect()
hook,并学习如何以及何时正确使用它。
理解 React useEffect hook
在 React 中,副作用包括数据获取、手动 DOM 操作或任何其他影响组件外部的操作。
要在函数组件中执行副作用,您使用 useEffect
hook。要使用 useEffect
hook,您首先需要从 react 库中导入它。
import { useEffect } from 'react';
Code language: JavaScript (javascript)
然后,您可以使用以下语法在您的组件中使用它。
useEffect(setup, dependencies)
Code language: JavaScript (javascript)
useEffect
hook 是一个接受两个参数的函数。
setup
是包含副作用的主要函数,您希望执行它。dependencies
是一个可选的依赖值数组,它决定了setup
函数何时运行。useEffect
hook 将根据dependencies
数组中指定的items
来运行setup
函数。
setup
函数可以选择返回一个清理函数。
return cleanup;
Code language: JavaScript (javascript)
React 在卸载组件或 setup
重新运行之前执行 cleanup
函数(除了第一次)。
在 cleanup
函数中,您可以包含用于清理资源的代码,例如清除间隔或取消网络请求 (AbortController
)。
通常,您会按如下方式编写 useEffect
hook。
useEffect(() => {
// Side effect code here
return () => {
// Cleanup code here (optional)
};
}, [dependencies]);
Code language: JavaScript (javascript)
在此语法中,您为 setup
函数定义一个箭头函数。
() => {
// Side effect code here
return () => {
// Cleanup code here (optional)
};
}
Code language: JavaScript (javascript)
并在 dependencies
数组中包含值。
[dependencies]
Code language: JavaScript (javascript)
只运行一次效果
要仅在组件挂载时运行效果(或函数),请使用空数组作为 dependencies
数组。
useEffect(() => {
// This code runs once
}, [])
Code language: JavaScript (javascript)
在实践中,您使用这种模式在组件的初始渲染期间运行函数。例如,您可以在组件挂载时仅运行一次从 API 获取数据的函数。
以下 UserList
组件通过调用 API 终结点 https://jsonplaceholder.typicode.com/users
来显示用户列表。
import React, { useEffect, useState } from 'react';
export default function UserList() {
const [users, setUsers] = useState([]);
const fetchUsers = async () => {
const url = 'https://jsonplaceholder.typicode.com/users';
const response = await fetch(url);
const data = await response.json();
setUsers(data);
};
useEffect(() => {
fetchUsers();
}, []);
return (
<div>
<h1>User List</h1>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
Code language: JavaScript (javascript)
每当依赖项更改时运行效果
要运行某些值更改时的函数,您可以在 dependencies
数组中指定这些值。
以下 CounterTitle
组件利用 useEffect()
hook 在 count
状态变量更改时更新文档标题。
import { useState, useEffect } from 'react';
const CounterTitle = () => {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);
return (
<div>
<h1>Current count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
export default CounterTitle;
Code language: JavaScript (javascript)
每次重新渲染后运行效果
要在初始渲染期间和每次重新渲染后运行函数,您只需将 setup
函数传递给 useEffect()
函数,并跳过 dependencies
数组。
例如,您可以使用 useEffect()
函数在组件渲染时以及每次重新渲染时记录一条消息。
import React, { useState, useEffect } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('Component rendered or rerendered');
});
return (
<div>
<h1>Current count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
export default Counter;
Code language: JavaScript (javascript)
运行清理函数
以下 WindowDimension
组件侦听窗口大小调整事件,并根据窗口的大小更新宽度和高度状态变量。
import { useState, useEffect } from 'react';
function WindowDimension() {
const [width, setWidth] = useState(window.innerWidth);
const [height, setHeight] = useState(window.innerHeight);
useEffect(() => {
// Define the handler function that updates the state with the window's width
const handleResize = () => {
setWidth(window.innerWidth);
setHeight(window.innerHeight);
};
// Add the event listener for window resize
window.addEventListener('resize', handleResize);
// Cleanup function: Remove the event listener when the component unmounts
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return (
<div>
<p>
Current dimension: {width}x{height}px
</p>
</div>
);
}
export default WindowDimension;
Code language: JavaScript (javascript)
工作原理。
首先,定义 handleResize()
函数来根据窗口的 innerWidth
和 innerHeight
更新宽度和高度状态变量。
const handleResize = () => {
setWidth(window.innerWidth);
setHeight(window.innerHeight);
};
Code language: JavaScript (javascript)
其次,使用 handleResize()
函数注册大小调整事件的事件侦听器。
window.addEventListener('resize', handleResize);
Code language: JavaScript (javascript)
第三,从 useEffect
返回一个清理函数,该函数使用 window.removeEventListener
方法删除大小调整事件侦听器。
return () => {
window.removeEventListener('resize', handleResize);
};
Code language: JavaScript (javascript)
这可以防止组件在从 DOM
中删除后调用 handleResize
函数,这可能会导致内存泄漏和意外行为。
总结
- 使用
useEffect(setup)
在组件渲染和重新渲染时运行setup
函数。 - 使用
useEffect(setup,[])
在初始渲染期间仅运行一次setup
函数。 - 使用
useEffect(setup, [dependencies])
在组件渲染时以及每次dependencies
数组中的项目更改时运行setup
函数。