数据 Hook
所有数据 Hook 都基于 TanStack Query v6,支持自动缓存、后台刷新和乐观更新。
所有数据 Hook 使用 <TData extends BaseRecord> 泛型实现类型安全的数据访问:
import type { BaseRecord } from '@svadmin/core';
interface Post extends BaseRecord { id: number; title: string; status: 'draft' | 'published';}
// TData 被推断为 Postconst query = useList<Post>({ resource: 'posts' });如果注册了 ResourceTypeMap,Hook 会自动推断类型并在编译时验证资源名称。
查询 Hook
Section titled “查询 Hook”所有查询 Hook 接受静态选项或getter 函数实现响应式选项:
// 静态useList({ resource: 'posts', filters: [{ field: 'status', operator: 'eq', value: 'published' }] });
// 响应式 getter — 当 $state 变化时自动重新请求useList(() => ({ resource: 'posts', pagination, sorters, filters }));useList
Section titled “useList”const query = useList<Post>({ resource: 'posts', pagination: { current: 1, pageSize: 10 } });// query.data → { data: Post[], total: number }useOne
Section titled “useOne”const query = useOne<Post>({ resource: 'posts', id: 1 });// query.data → { data: Post }useShow(useOne 的别名)
Section titled “useShow(useOne 的别名)”const query = useShow<Post>({ resource: 'posts', id: 1 });useMany
Section titled “useMany”const query = useMany<Post>({ resource: 'posts', ids: [1, 2, 3] });// query.data → { data: Post[] }useSelect
Section titled “useSelect”const query = useSelect({ resource: 'categories', optionLabel: 'name', optionValue: 'id', defaultValue: [1, 2], // 预选值 searchField: 'name', // 服务端搜索 debounce: 300, // 搜索防抖(毫秒)});// query.options → [{ label: '技术', value: '1' }, ...]// query.onSearch → (value: string) => voiduseInfiniteList
Section titled “useInfiniteList”const query = useInfiniteList<Post>({ resource: 'posts', pageSize: 20 });// query.fetchNextPage() — 加载下一页// query.hasNextPage — booleanuseCustom
Section titled “useCustom”const query = useCustom<{ stats: number[] }>({ url: '/api/dashboard/stats', method: 'get',});// query.data → { data: { stats: number[] } }useApiUrl
Section titled “useApiUrl”const apiUrl = useApiUrl(); // → 'https://api.example.com'变更 Hook
Section titled “变更 Hook”useCreate
Section titled “useCreate”const mutation = useCreate<Post>();mutation.mutate({ resource: 'posts', variables: { title: '你好' } });useUpdate
Section titled “useUpdate”const mutation = useUpdate<Post>();mutation.mutate({ resource: 'posts', id: 1, variables: { title: '已更新' } });useDelete
Section titled “useDelete”const mutation = useDelete();mutation.mutate({ resource: 'posts', id: 1 });useCustomMutation
Section titled “useCustomMutation”const mutation = useCustomMutation();mutation.mutate({ url: '/api/posts/publish', method: 'post', values: { ids: [1, 2] } });批量操作:useCreateMany、useUpdateMany、useDeleteMany
Section titled “批量操作:useCreateMany、useUpdateMany、useDeleteMany”与单条操作相同的模式,使用数组。
useInvalidate
Section titled “useInvalidate”手动刷新缓存的查询:
const invalidate = useInvalidate();invalidate({ resource: 'posts', invalidates: ['list', 'one'] });所有变更 Hook 通过 mutationMode 支持三种模式:
| 模式 | 行为 |
|---|---|
pessimistic | 等待服务端响应(默认) |
optimistic | 立即更新 UI,出错时回滚 |
undoable | 显示撤销提示,延迟 undoableTimeout 毫秒后再调用服务端 |
const mutation = useUpdate({ mutationMode: 'undoable', undoableTimeout: 5000 });