关于 react-ban-use-effect
面向 React 开发的技能,用于审查直接调用 `useEffect` 的代码,并按行为选择替代方案。它指导局部迁移、合法的外部系统 Hook 设计,以及 lint 和测试验证。
主要功能
- 01分类直接调用与包装器
- 02优先采用渲染、数据、事件或键控方案
- 03定义范围明确的外部系统 Hook
- 04设置限定范围的 lint 规则
- 05通过项目门禁验证变更
适用场景
- 01审查 React 代码中的非必要副作用
- 02迁移指定代码区域内的副作用
- 03说明外部同步边界的合理性
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ uinaf/ agent-skills --skill react-ban-use-effect安装后在 Claude Code 中输入/react-ban-use-effect确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/mechanical-effect-guardrail/criteria.jsontask.mdevals/vendor-map-widget/criteria.jsontask.mdreferences/replacements.mdupstream.md详细介绍
React 禁用 useEffect
直接使用 useEffect 是用于逃避外部同步的出口。组件不得调用它;只有针对真实外部系统、经过审核的领域专用钩子可以调用。
范围
替换 Effect 会改变涉及的行为。全仓库的 lint 强制检查是单独的任务:仅在收到请求或现有仓库策略要求时才应用。代码审查请求只需指出问题;实现请求则授权在范围内进行替换和验证,无需再经过批准。
工作流
-
在涉及的范围内查找直接导入、
React.useEffect(...)命名空间调用,以及对useEffect的封装。 -
对每个 Effect 进行分类,并按以下优先顺序替换:
- 渲染时计算
- 服务端、loader 或框架数据 API
- 仓库的服务端状态层(例如,使用变量作为 key 并透传
signal的 TanStack QueryqueryOptions工厂) - 事件处理程序、action 或 mutation
- 以 key 为界的组件边界
useSyncExternalStore- 针对真实外部系统、经过审核的领域专用钩子
如果以上都不适用,保留 Effect 前应说明外部同步契约。替换方案介绍了不那么显而易见的情况。
-
保留仓库的框架、数据层、lint 形式和依赖策略。只有请求或仓库策略授权时才添加库;如果没有服务端状态层,应将剩余的 Effect 称为设计缺口。
-
运行 lint、类型检查和测试关卡,并针对变更的行为进行最小范围的真实 UI 或钩子检查。
合法的 Effect
将每个合法的 Effect 放在以其外部系统命名的钩子中(例如聊天连接、地图 SDK 或小组件),并单独存放在一个文件中。钩子负责设置和清理,通过参数接收其响应式输入,并列出设置或清理时读取的每个值。调用它的组件应保持不含 Effect。优先使用仓库中已有的钩子。
切勿:
- 编写接收回调和调用方提供的依赖数组的通用封装(
useUpdateEffect(fn, deps)、useAsyncEffect(fn, deps)、useMountEffect(fn)); - 禁用
react-hooks/exhaustive-deps; - 使用例外钩子获取服务端状态、将 props 复制到 state、转发用户操作,或隐藏本应在以 key 为界的边界处进行的重置。
强制检查
当强制检查属于任务范围时,扩展仓库现有的 linter,使其拒绝具名导入的 useEffect 和 React.useEffect(...) 调用。仅允许位于具名且经过审核的集成钩子文件中,不得放行整个目录(例如 src/hooks/**),也不得放行通用封装;将封装及其调用方都报告为待迁移的违规项。保留规范的本地检查关卡,并确保 CI 针对同一 lint 范围运行;Agent 指引或可选扫描器不能替代它。不要使用 @latest 诊断工具进行持久化强制检查。
在代码审查中,除非变更记录并证明了合法的外部系统边界,否则每个新的直接 Effect 都是一个问题。应要求替换,而不是调整依赖数组。
边界
- 迁移范围仅限于涉及或指定的部分。
- 除非收到请求,否则不要改动
useLayoutEffect、useInsertionEffect、框架生命周期 API 和非 React 的 Effect 系统,包括 lint 规则中的相关检查。 - 仅在有测量结果或仓库已有成熟模式时应用性能原语。
- 上游归属:upstream。