Studio Web 项目结构一览 - Redux + React Query 方案
📋 各层职责一览表
| 层级 | 位置 | 职责 | 可以做 | 不能做 |
|---|---|---|---|---|
| Component | components/ | UI 渲染 | • 渲染 JSX • 绑定事件 • 调用 Hook | • 直接访问 Store • 包含业务逻辑 • HTTP 请求 |
| Hook | hooks/ | 能力封装 | • 封装 Core 方法 • 订阅 Store • 生命周期处理 • 计算派生状态 | • 包含核心业务逻辑 • 直接调用 Service • 复杂的流程编排 |
| Core ⭐ | lib/core/ | 业务逻辑 | • 所有业务逻辑 • 流程编排 • 调用 Store/Query • 处理副作用 | • 渲染 UI • 操作 DOM • 直接访问组件状态 |
| Store | store/ | 状态管理 | • 定义状态 • 更新状态 • 持久化 | • 业务逻辑 • HTTP 请求 • 复杂计算 |
| Query | hooks/queries/ | 数据缓存 | • 封装请求 • 缓存策略 • 调用 Service | • 业务流程编排 • 状态管理 |
| Service | service/ | HTTP 请求 | • 纯 HTTP 请求 • 数据序列化 | • 业务逻辑 • 状态管理 • UI 交互 |
| Utils | utils/ | 工具函数 | • 格式化 • 验证 • 底层操作 | • 业务流程 • 状态管理 |
数据流转路径
- Component → Query Hook → Service → apiClient/Utils 不经过 Store。对于简单逻辑 Query = Core + Store + Service,所以也不需要经过 Core 了,Query 的缓存就是该服务器数据的权威来源。【服务端状态】
- Component → useAuth Hook → Core → Service → apiClient/Utils Core 负责写 Store(isAuthenticated、isLoading、必要的用户概要),useAuth 读 Store。【复杂流程编排】
依赖方向:Component → Store(读),Core → Store(写),Query Hook ⇏ Store(默认不写),Service ⇏ Store(禁止)
Core 直接调用 Service 层,不调用 Query 层
Hook 可以直接调用 Query 层,Query 层的作用是数据获取/缓存,和 Core 层各有侧重点,复杂流程编排时再调用 Core 层
Store 不在“数据请求链路”中。它是客户端状态源(UI/会话),独立于 Query/Service。服务器状态(列表/详情/userinfo 等)用 TanStack Query 管理,不复制到 Store,避免“双写”和陈旧数据。
📁 目录结构
Studio Web/
├── types/ # 📝 TypeScript类型定义
│ ├── api.d.ts # 🔌 API响应类型定义
│ ├── store.d.ts # 📦 Redux状态类型定义
│ └── global.d.ts # 🌐 全局类型声明
├── app/ # 🚀 Next.js App Router (页面/路由/布局)
├── components/ # 🧩 React组件库
│ ├── features/ # 📋 业务功能组件 (UserProfile/Dashboard)
│ ├── layout/ # 🏗️ 布局组件 (Header/Footer/Sidebar)
│ └── ui/ # 🎨 基础UI组件 (Button/Input/Modal)
├── configs/ # ⚙️ 应用配置 (环境变量/常量配置)
├── hooks/ # 🎣 自定义Hooks
├── i18n/ # 🌍 国际化 (多语言翻译文件)
├── lib/ # 📚 第三方库配置
│ ├── react-query.ts # ⚡ React Query客户端配置
│ └── redux.ts # 📦 Redux Store配置
├── service/ # 🔌 API服务层 (纯HTTP请求函数)
├── store/ # 📦 Redux状态管理 (客户端状态)
│ ├── slices/ # 🔪 Redux切片 (auth/ui/filters等)
│ └── index.ts # 🏪 Store配置和导出
└── utils/ # 🛠️ 工具函数 (格式化/验证/通用方法)
🔄 数据流转架构图
完整数据流程
用户交互 → Component → Hook (分流) → 不同状态管理
↓ ↓ ↓ ↓
事件触发 UI渲染 状态查询 执行操作
↑ ↑ ↑ ↑
UI更新 ← Component ← Hook ←── 状态更新通知
服务端状态流 (React Query)
Component → hooks/queries/useUsers → service/userService → API
↓ ↓ ↓ ↓
调用Hook 执行查询 HTTP请求 后端处理
↑ ↑ ↑ ↑
自动更新 ← React Query缓存 ← userService ← API Response
客户端状态流 (Redux)
Component → hooks/store/useAuth → store/slices/authSlice → Redux Store
↓ ↓ ↓ ↓
触发Action 调用dispatch 执行Reducer 状态更新
↑ ↑ ↑ ↑
重新渲染 ← useSelector ← store/index.ts ← 状态变更通知
🎯 各模块功能详细划分
📊 状态管理职责分工
| 状态类型 | 管理工具 | 存储位置 | 典型用例 |
|---|---|---|---|
| 服务端状态 | React Query | Hook缓存 | 用户数据、产品列表、订单信息 |
| 客户端状态 | Redux | Store | 认证状态、UI状态、表单状态 |
🔌 Service 层 (纯API调用)
// service/userService.ts
export const userService = {
// 纯粹的HTTP请求,无状态逻辑
getUsers: () => fetch('/api/users').then(res => res.json()),
createUser: (data) => fetch('/api/users', { method: 'POST', body: JSON.stringify(data) })
}
🎣 Hooks 层 (状态管理桥梁)
hooks/queries/ - 服务端状态管理
// hooks/queries/useUsers.ts
export const useUsers = (filters) => {
return useQuery({
queryKey: ['users', filters],
queryFn: () => userService.getUsers(filters),
staleTime: 5 * 60 * 1000, // 缓存策略
})
}
export const useCreateUser = () => {
return useMutation({
mutationFn: userService.createUser,
onSuccess: () => queryClient.invalidateQueries(['users'])
})
}
hooks/store/ - 客户端状态管理
// hooks/store/useAuth.ts
export const useAuth = () => {
const dispatch = useDispatch()
return {
...useSelector(state => state.auth),
login: (credentials) => dispatch(login(credentials)),
logout: () => dispatch(logout())
}
}
📦 Store 层 (客户端状态)
// store/slices/authSlice.ts - 认证状态
const authSlice = createSlice({
name: 'auth',
initialState: { user: null, isAuthenticated: false },
reducers: { login, logout }
})
// store/slices/uiSlice.ts - UI状态
const uiSlice = createSlice({
name: 'ui',
initialState: { sidebarOpen: false, theme: 'light' },
reducers: { toggleSidebar, setTheme }
})
📚 Lib 层 (第三方库配置)
// lib/react-query.ts
export const queryClient = new QueryClient({
defaultOptions: {
queries: { staleTime: 60 * 1000, cacheTime: 5 * 60 * 1000 }
}
})
// lib/redux.ts
export const store = configureStore({
reducer: {
auth: authSlice.reducer,
ui: uiSlice.reducer
}
})
🏗️ 实际使用示例
复杂页面组件
// app/dashboard/page.tsx
'use client'
export default function DashboardPage() {
// 服务端状态 (React Query)
const { data: users, isLoading } = useUsers()
const { data: orders } = useOrders()
const createUserMutation = useCreateUser()
// 客户端状态 (Redux)
const { isAuthenticated } = useAuth()
const { sidebarOpen, filters } = useUI()
return <Dashboard {...props} />
}
Data Flow Summary Diagram
┌──────────────────────────────────────────────────────────────┐
│ Component Layer │
│ (UI Rendering) │
│ │
│ • Responsible for UI rendering and event binding │
│ • No direct Store access │
│ • No business logic │
│ │
│ Example: │
│ const { login, isAuth } = useAuth() ← Call Hook only │
│