[ PROMPT_NODE_25290 ]
react-useeffect
[ SKILL_DOCUMENTATION ]
# 你可能不需要副作用 (Effect)
副作用是 React 的**逃生舱**。它们用于与外部系统同步。如果没有涉及外部系统,你就不应该需要副作用。
## 快速参考
| 情况 | 不要 (DON'T) | 要 (DO) |
|-----------|-------|-----|
| 从 props/state 派生状态 | `useState` + `useEffect` | 在渲染期间计算 |
| 昂贵的计算 | `useEffect` 缓存 | `useMemo` |
| 在 prop 改变时重置状态 | `useEffect` + `setState` | `key` 属性 |
| 用户事件响应 | `useEffect` 监听状态 | 直接使用事件处理器 |
| 通知父组件变更 | `useEffect` 调用 `onChange` | 在事件处理器中调用 |
| 获取数据 | `useEffect` 无清理 | `useEffect` 带清理 或 使用框架 |
## 何时需要副作用
- 与**外部系统**同步 (非 React 组件、浏览器 API)
- **订阅**外部存储 (尽可能使用 `useSyncExternalStore`)
- 因组件显示而运行的**分析/日志记录**
- 带有正确清理机制的**数据获取** (或使用框架内置机制)
## 何时不需要副作用
1. **转换渲染数据** - 在顶层计算,会自动重新运行
2. **处理用户事件** - 使用事件处理器,你确切知道发生了什么
3. **派生状态** - 直接计算:`const fullName = firstName + ' ' + lastName`
4. **链式状态更新** - 在事件处理器中计算所有后续状态
## 决策树
需要响应某事吗?
├── 用户交互 (点击, 提交, 拖拽)?
│ └── 使用事件处理器 (EVENT HANDLER)
├── 组件出现在屏幕上?
│ └── 使用副作用 (EFFECT) (外部同步, 分析)
├── Props/state 改变且需要派生值?
│ └── 在渲染期间计算 (CALCULATE DURING RENDER)
│ └── 昂贵? 使用 useMemo
└── 需要在 prop 改变时重置状态?
└── 在组件上使用 KEY 属性
## 详细指南
- [反模式](./anti-patterns.md) - 常见错误及修复
- [更好的替代方案](./alternatives.md) - useMemo, key 属性, 状态提升, useSyncExternalStore