tanstack-querylisted
Install: claude install-skill beixiyo/dotfiles
项目不是 v5、API 语义不确定或涉及版本差异时,先查当前版本官方文档,不凭印象套用 v5
## 状态边界
使用 TanStack Query 管理来自服务器、可能过期且需要同步的数据
不要把以下内容默认放入 Query Cache:
- 表单输入
- 弹窗开关
- 当前 tab
- 尚未提交的纯本地草稿
- 只属于单个组件的派生 UI 状态
Mutation 不会自动同步 Query Cache。调用方必须根据服务端响应决定写缓存还是失效查询
## Query key
顶层使用数组,并包含所有会改变 `queryFn` 结果的输入:
```tsx
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,
}
```
遵循:
- 从资源到范围再到参数:`resource → list/detail → filters/id`
- 共享资源根前缀,支持精确和批量操作
- 把分页、筛选、排序、租户、语言等查询输入放进 key
- 对象属性顺序不影响哈希,数组元素顺序影响哈希
- 不用互不相关的 `cards-todo`、`card-detail` 顶层 key 表示同一资源
- 优先复用 factory,不在调用点散落字符串数组
Query key 描述缓存身份,不会自动建立查询执行依赖
## useQuery
让 `queryFn` 抛出错误并消费 `AbortSignal`(仅在需要的情况下)
```tsx
const userQuery = useQuery({
queryKey: userKeys.detail(userId),
queryFn: ({ signal }) => api.user.get(userId, { signal }),
enabled: userId !== undefined,
})
```
v5 状态语义:
| 状态 | 含义 |
| ---------------- | ------------------------------------ |
| `isPending` | 尚无成功数据 |
| `isFetching` | 当前正在请求,包括首次请求和 refetch |
| `isLoading` | `isPending && isFetching` |
| `isRefetching` | 已有数据时正在重新请求 |
| `isLoadingError` | 首次加载失败,没有可展示数据 |
| `isRefetchError` | 已有数据时后台请求失败 |
注意: