1.9 KiB
1.9 KiB
Hook 与数据请求
API 适配三件套
服务端数据按 feature 放置为 API 函数、query hook 和类型文件:
features/system/api/system.types.ts定义SystemStatus。features/system/api/system.api.ts:getSystemStatus调用 shared transport,并把AbortSignal传给fetch。features/system/api/system.query.ts:useSystemStatus暴露 React Query hook,并使用systemStatusQueryKey。
页面只调用 useSystemStatus,不直接调用 fetch。新增 feature 应保持同样分层。
export const systemStatusQueryKey = ["system", "status"] as const
export function useSystemStatus() {
return useQuery({
queryFn: ({ signal }) => getSystemStatus(signal),
queryKey: systemStatusQueryKey,
})
}
React Query
- 服务器状态由 TanStack Query 管理;公共默认值在
app/query-client.ts(不跟随窗口刷新、失败重试 1 次、staleTime30 秒)。 - query key 使用
as const常量,避免页面散落字符串。 - 使用 query function 提供的
signal支持取消请求;不要忽略它或在页面手写生命周期 fetch。 - 页面显式处理
isPending、isError和data,参照SystemStatusPage。
Hook 命名与副作用
- 自定义 hook 以
use开头并表达资源或行为,例如useSystemStatus、useUiStore。 - 纯数据 hook 不执行额外副作用;需要同步 DOM 的副作用集中在
app/providers.tsx:ThemeEffect,由 Zustand 主题驱动document.documentElement的 class。 - 不要把一个 hook 同时用作服务器缓存和 UI 偏好存储;两者分别使用 React Query 与 Zustand。
反模式
- 不要在组件中直接
fetch、重复设置 query key 或把响应复制到本地useState。 - 不要用 Zustand 保存 API 响应以“共享”数据,也不要用 React Query 保存主题等本地偏好。
- 不要为了复用一次性的
useEffect创建泛化 hook;先确认是否已有跨页面重复模式。