用 AI 快速上手现代 React 状态管理方案
解决前端状态混乱痛点:当需要构建全局状态、处理服务端数据缓存或迁移旧版 Redux 时,该技能能自动匹配最佳工具(Zustand/Redux/RTK),输出类型安全且遵循最佳实践的初始化代码。
为什么需要这个技能
React 应用随着功能增加,状态管理方案的选择至关重要。 新手常混淆组件内部状态(useState)与全局状态(Redux/Zustand)。 此外,如何处理异步服务器数据缓存也是常见难题。
本技能通过分析你的项目规模和复杂度,自动推荐 Zustand(轻量)、Redux Toolkit(生态成熟)或 Jotai(原子化)等方案,并生成包含持久化、优化更新和类型推导的完整代码模板,避免重复造轮子。
适用场景
- 正在初始化一个新的 React 项目,需要在配置阶段选定状态库。
- 需要将原有的 Redux store 迁移到更现代的 Zustand 或 Jotai。
- 需要区分处理服务端 API 数据(React Query)与客户端 UI 状态。
- 想要实现乐观更新(Optimistic Updates)或复杂的原子状态逻辑。
核心工作流
-
评估项目规模与需求:
- 小应用或简单状态:推荐使用 Zustand 或 Jotai。
- 大型复杂应用:推荐 Redux Toolkit 搭配 RTK Query。
- 重型服务器交互:必须引入 React Query 或 SWR。
-
选择工具并生成架构:
- 根据
Selection Criteria自动生成对应的 Store 结构。 - 自动生成 TypeScript 类型定义,确保
RootState和AppDispatch的类型安全。
- 根据
-
实施具体模式:
- 使用 Zustand 快速搭建原子状态或持久化存储。
- 使用 React Query 处理
useQuery和useMutation,自动处理缓存失效和回退。 - 实现 Jotai 的原子状态(Atom)和派生状态(Derived Atom)。
代码示例
Zustand (最简洁)
适用于简单状态,开箱即用,支持持久化。
// store/useStore.ts
import { create } from 'zustand'
import { devtools, persist } from 'zustand/middleware'
interface AppState {
user: User | null
theme: 'light' | 'dark'
setUser: (user: User | null) => void
toggleTheme: () => void
}
export const useStore = create<AppState>()(
devtools(
persist(
(set) => ({
user: null,
theme: 'light',
setUser: (user) => set({ user }),
toggleTheme: () => set((state) => ({
theme: state.theme === 'light' ? 'dark' : 'light'
})),
}),
{ name: 'app-storage' }
)
)
)
// Usage in component
function Header() {
const { user, theme, toggleTheme } = useStore()
return (
<header className={theme}>
{user?.name}
<button onClick={toggleTheme}>Toggle Theme</button>
</header>
)
}
Redux Toolkit with TypeScript
适用于大型应用,包含完善的切片(Slice)和类型推导。
// store/index.ts
import { configureStore } from '@reduxjs/toolkit'
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import userReducer from './slices/userSlice'
import cartReducer from './slices/cartSlice'
export const store = configureStore({
reducer: {
user: userReducer,
cart: cartReducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: ['persist/PERSIST'],
},
}),
})
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
// Typed hooks
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
// store/slices/userSlice.ts
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
interface User {
id: string
email: string
name: string
}
interface UserState {
current: User | null
status: 'idle' | 'loading' | 'succeeded' | 'failed'
error: string | null
}
const initialState: UserState = {
current: null,
status: 'idle',
error: null,
}
export const fetchUser = createAsyncThunk(
'user/fetchUser',
async (userId: string, { rejectWithValue }) => {
try {
const response = await fetch(`/api/users/${userId}`)
if (!response.ok) throw new Error('Failed to fetch user')
return await response.json()
} catch (error) {
return rejectWithValue((error as Error).message)
}
}
)
const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
setUser: (state, action: PayloadAction<User>) => {
state.current = action.payload
state.status = 'succeeded'
},
clearUser: (state) => {
state.current = null
state.status = 'idle'
},
},
extraReducers: (builder) => {
builder
.addCase(fetchUser.pending, (state) => {
state.status = 'loading'
state.error = null
})
.addCase(fetchUser.fulfilled, (state, action) => {
state.status = 'succeeded'
state.current = action.payload
})
.addCase(fetchUser.rejected, (state, action) => {
state.status = 'failed'
state.error = action.payload as string
})
},
})
export const { setUser, clearUser } = userSlice.actions
export default userSlice.reducer
Zustand with Slices (可扩展)
通过组合函数将多个 Slice 整合到一个 Store。
// store/slices/createUserSlice.ts
import { StateCreator } from 'zustand'
export interface UserSlice {
user: User | null
isAuthenticated: boolean
login: (credentials: Credentials) => Promise<void>
logout: () => void
}
export const createUserSlice: StateCreator<
UserSlice & CartSlice, // Combined store type
[],
[],
UserSlice
> = (set, get) => ({
user: null,
isAuthenticated: false,
login: async (credentials) => {
const user = await authApi.login(credentials)
set({ user, isAuthenticated: true })
},
logout: () => {
set({ user: null, isAuthenticated: false })
// Can access other slices
// get().clearCart()
},
})
React Query for Server State
分离服务端状态,自动处理缓存、重试和乐观更新。
// hooks/useUsers.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
// Query keys factory
export const userKeys = {
all: ['users'] as const,
lists: () => [...userKeys.all, 'list'] as const,
list: (filters: UserFilters) => [...userKeys.lists(), filters] as const,
details: () => [...userKeys.all, 'detail'] as const,
detail: (id: string) => [...userKeys.details(), id] as const,
}
// Fetch hook
export function useUsers(filters: UserFilters) {
return useQuery({
queryKey: userKeys.list(filters),
queryFn: () => fetchUsers(filters),
staleTime: 5 * 60 * 1000, // 5 minutes
gcTime: 30 * 60 * 1000, // 30 minutes (formerly cacheTime)
})
}
// Mutation with optimistic update
export function useUpdateUser() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: updateUser,
onMutate: async (newUser) => {
// Cancel outgoing refetches
await queryClient.cancelQueries({ queryKey: userKeys.detail(newUser.id) })
// Snapshot previous value
const previousUser = queryClient.getQueryData(userKeys.detail(newUser.id))
// Optimistically update
queryClient.setQueryData(userKeys.detail(newUser.id), newUser)
return { previousUser }
},
onError: (err, newUser, context) => {
// Rollback on error
queryClient.setQueryData(
userKeys.detail(newUser.id),
context?.previousUser
)
},
onSettled: (data, error, variables) => {
// Refetch after mutation
queryClient.invalidateQueries({ queryKey: userKeys.detail(variables.id) })
},
})
}
最佳实践
- 状态就近原则 (Colocate state):状态尽量靠近使用它的组件。
- 使用选择器 (Selectors):配合 Zustand 或 Redux 使用选择器防止不必要的重渲染。
- 规范化数据 (Normalize data):扁平化嵌套结构以便于更新。
- 类型覆盖 (Type everything):使用 TypeScript 防止运行时错误。
- 不要过度全局化:非核心交互逻辑不必放入全局 Store。
下载和安装
下载 react-state-management 中文版 Skill ZIP
解压后将目录放入你的 AI 工具 skills 文件夹,重启工具后即可使用。
你可能还需要
暂无推荐