关于 frontend-review-state
此技能为前端项目提供状态管理架构审查流程,供评估状态库使用方式的工程团队采用。它帮助识别状态分类错误、全局状态反模式及登出后的缓存清理缺口,并生成审查报告。
主要功能
- 01盘点状态管理库与用法
- 02检查服务端、URL 和表单状态分类
- 03审查 Jotai、Zustand、Redux 与 Context
- 04检查登出时的缓存和状态清理
- 05生成含文件行号的审查报告
适用场景
- 01查找误存于全局状态的服务端数据
- 02审查大型 atom、store 或粗粒度订阅
- 03检查用户登出后的缓存失效
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mizchi/ skills --skill frontend-review-state安装后在 Claude Code 中输入/frontend-review-state确认已加载。
附带文件README.md
详细介绍
前端审查 — 状态管理
你正在审查前端项目的状态管理架构。最常见的 AI 生成问题包括:把所有内容都放进全局状态、将服务端数据存储在全局状态仓库中而不是使用 TanStack Query,以及使用粒度过粗的选择器,导致整个组件树重新渲染。
流程
- 阅读
package.json,确认正在使用的状态管理库。 - 搜索全局状态的使用模式:
# Jotai grep -rn "atom\|useAtom\|useAtomValue" src/ --include='*.ts' --include='*.tsx' | wc -l # Zustand grep -rn "create\b\|useStore\b" src/ --include='*.ts' --include='*.tsx' | head -20 # Redux grep -rn "createSlice\|useSelector\|useDispatch" src/ --include='*.ts' --include='*.tsx' | head -20 # Context grep -rn "createContext\|useContext" src/ --include='*.ts' --include='*.tsx' | head -20 - 抽查 3–5 个规模最大的 atom / store 定义,并评估其中包含的内容。
- 检查是否有服务端状态存储在全局状态仓库中(应该改用 TanStack Query / SWR)。
- 检查是否有 URL 状态存储在全局状态仓库中(应该改用
useSearchParams/nuqs)。 - 检查是否有表单状态存储在全局状态仓库中(应该改用 React Hook Form)。
状态分类
正确地按类型分类状态。每种类型都有专用工具;使用错误的工具是大多数状态管理缺陷的根本原因。
Server state → TanStack Query / SWR (not global store)
URL state → useSearchParams / nuqs (not global store)
Form state → React Hook Form (not global store)
UI local → useState / useReducer (component-scoped)
UI global → Jotai / Zustand / Context (minimum scope)
标记全局 Jotai/Zustand/Redux 状态仓库中发现的任何服务端、URL 或表单状态。这些始终属于缺陷或设计错误。
特定库检查项
Jotai
- Atom 粒度:每个逻辑单元使用一个 atom;不要使用大型对象 atom(
{ user, theme, notifications, ... })。 - 派生状态:对于计算值,使用
atom(get => ...),而不是存储冗余的计算数据。 - 副作用:将副作用隔离在
atomEffect/useAtomEffect中,而不是放在atomsetter 回调中。 - 可测试性:在模块顶层声明的 atom 会成为全局单例;在测试 / Storybook 中使用
Provider进行作用域隔离。
// Bad: monolithic atom
const appStateAtom = atom({ user: null, theme: 'light', selectedItems: [], filterQuery: '' });
// Good: split + derived
const userAtom = atom<User | null>(null);
const themeAtom = atom<'light' | 'dark'>('light');
const filteredItemsAtom = atom((get) =>
get(allItemsAtom).filter(item => item.name.includes(get(filterQueryAtom)))
);
Zustand
- 选择器用法:使用
useStore(state => state.specificField);绝不要订阅整个 store 对象。 - 浅比较:将多个字段作为对象进行选择时,使用
zustand/shallow中的shallow。 - 禁止直接修改:始终使用
set/get,绝不要在 Zustand 的 setter 之外修改状态。
// Bad: subscribes to everything
const { user, theme, cart } = useStore();
// Good: selector per field (or shallow for multi-field)
const user = useStore(state => state.user);
const { theme, cart } = useStore(useShallow(state => ({ theme: state.theme, cart: state.cart })));
Redux Toolkit
- 是否使用了
createSlice(而不是手写 reducer)? - 异步数据是否通过
createAsyncThunk或 RTK Query 获取,而不是使用手动的dispatch链? - 服务端状态是否放在 RTK Query / TanStack Query 中,而不是放在 slice 中?
Context API
- Context 的值发生任何变化时,都会触发每个 Consumer 重新渲染。如果 context 值是一个对象,应按逻辑分组拆分为独立的 context(例如
AuthContext、ThemeContext)。 - Context 适用于稳定且低频变化的值(身份验证用户、主题、i18n 区域设置)。
- 不要将 Context 用作处理高频更新的通用状态管理器。
登出与缓存失效
一个常见缺陷:登出后,下一个登录的用户会看到上一个会话的缓存数据。
检查登出处理程序是否:
- 调用服务端登出端点(撤销会话)
- 清除 TanStack Query / SWR 缓存(
queryClient.clear()) - 重置所有身份验证相关的全局 atom / Zustand store
- 导航至
/login(清除之后,而不是之前)
输出
在 <client-repo>/.frontend-review/report/latest/md/state-review.md 中写入:
- 状态清单:使用了哪些库,atom/store/context 的大致数量
- 错误分类的状态:在全局状态仓库中发现的服务端 / URL / 表单状态(这些属于缺陷)
- 发现的反模式:附上文件:行号引用
- 登出 / 缓存缺口(如有)
- 建议的 PR:每项仅涉及一个逻辑重构
内容保持在 200 行以内。文件级详情保留在原始搜索输出中,不要写进报告。
边界
- 不要重写状态管理代码。报告用于指出缺口;修复由工程团队实施。
- 不要修改客户端仓库中的源文件。
- 渲染性能(重新渲染、memo 用法)由
frontend-review-performance负责。
参考
- 检查清单:
23-state-management.md、17-pure-io-separation.md、21-api-layer.md - 相关内容:
frontend-review-performance(重新渲染分析)
评论
支持 Markdown