
useEffect 是 React 函数组件中处理副作用的核心钩子,用于替代类组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount,支持按需执行(如挂载时、状态变化时)并提供优雅的清理能力。
useeffect 是 react 函数组件中处理副作用的核心钩子,用于替代类组件中的 `componentdidmount`、`componentdidupdate` 和 `componentwillunmount`,支持按需执行(如挂载时、状态变化时)并提供优雅的清理能力。
useEffect 是 React Hooks 体系中最关键、也最易被误解的钩子之一。它本质上是函数组件“连接外部世界”的桥梁——无论是发起 API 请求、操作 DOM、设置定时器,还是订阅事件,只要涉及与 React 渲染周期之外的系统交互(即“副作用”),都应通过 useEffect 统一管理。
核心行为:执行时机由依赖数组决定
useEffect 的行为完全由其第二个参数——依赖数组(dependency array)控制:
无依赖数组(useEffect(() => {...}))
每次组件重新渲染后都会执行(含初始挂载)。⚠️ 易引发无限循环或性能问题,不推荐在生产环境直接使用。空依赖数组(useEffect(() => {...}, []))
仅在组件首次挂载(mount)时执行一次,等效于 componentDidMount。适合初始化逻辑,如加载数据、设置全局监听器。含依赖项的数组(useEffect(() => {...}, [a, b]))
在组件挂载时执行,并在数组中任一值发生浅比较变化时重新执行。这是最常用模式,适用于响应状态或 props 变化(例如:用户输入更新后触发搜索请求)。
清理函数:防止内存泄漏的关键机制
useEffect 的回调函数可选择性返回一个清理函数(cleanup function),该函数会在以下时机自动调用:
已弃用 — 请改用 `auth0` 技能(运行 `npx clawhub install auth0`)。适用于为 React 单页应用(SPA)添加 Auth0 登录、登出、受保护路由或用户会话功能。该技能集成 `@auth0/auth0-react` — 即使用户仅表述为“为我的 React 应用添加登录功能”或“保护我的 React 路由”,而未明确提及 Auth0,也应使用此技能。
- 下一次 effect 执行前(若依赖变化)
- 组件卸载(unmount)前
这使得资源释放(如清除定时器、取消网络请求、移除事件监听器)变得安全且声明式:
useEffect(() => {
const timer = setTimeout(() => {
console.log('Timer fired');
}, 1000);
// 返回清理函数:组件卸载或下次 effect 运行前清除定时器
return () => clearTimeout(timer);
}, []);实用示例:带清理的计时器组件
以下是一个完整、健壮的计时器实现,体现挂载初始化 + 自动清理:
import { useState, useEffect } from 'react';
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
const timerId = setInterval(() => {
setCount(prev => prev + 1);
}, 1000);
// 清理:组件卸载时清除定时器,避免 setState on unmounted component 警告
return () => clearInterval(timerId);
}, []); // 空依赖 → 仅挂载时启动,卸载时清理
return <h1>已运行 {count} 秒</h1>;
}
export default Timer;注意事项与最佳实践
- ✅ 始终检查依赖项完整性:若 effect 中使用了某个 state 或 prop,它必须出现在依赖数组中,否则将导致陈旧闭包(stale closure)问题。
- ✅ 异步操作需注意清理:发起的 fetch 请求应在清理函数中通过 AbortController 取消;避免对已卸载组件调用 setState。
- ❌ 不要在条件语句中调用 useEffect:违反 Hook 规则(必须顶层调用),会导致渲染逻辑错乱。
- ? 使用 eslint-plugin-react-hooks 插件自动检测依赖遗漏或错误。
掌握 useEffect 的本质——“何时执行”由依赖数组声明,“如何收尾”由返回函数保障——你就掌握了函数组件副作用管理的主动权。它不是魔法,而是 React 将生命周期控制权交还给开发者的精准设计。

















