跳转到内容

数据 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 被推断为 Post
const query = useList<Post>({ resource: 'posts' });

如果注册了 ResourceTypeMap,Hook 会自动推断类型并在编译时验证资源名称。

所有查询 Hook 接受静态选项或getter 函数实现响应式选项:

// 静态
useList({ resource: 'posts', filters: [{ field: 'status', operator: 'eq', value: 'published' }] });
// 响应式 getter — 当 $state 变化时自动重新请求
useList(() => ({ resource: 'posts', pagination, sorters, filters }));
const query = useList<Post>({ resource: 'posts', pagination: { current: 1, pageSize: 10 } });
// query.data → { data: Post[], total: number }
const query = useOne<Post>({ resource: 'posts', id: 1 });
// query.data → { data: Post }
const query = useShow<Post>({ resource: 'posts', id: 1 });
const query = useMany<Post>({ resource: 'posts', ids: [1, 2, 3] });
// query.data → { data: Post[] }
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) => void
const query = useInfiniteList<Post>({ resource: 'posts', pageSize: 20 });
// query.fetchNextPage() — 加载下一页
// query.hasNextPage — boolean
const query = useCustom<{ stats: number[] }>({
url: '/api/dashboard/stats',
method: 'get',
});
// query.data → { data: { stats: number[] } }
const apiUrl = useApiUrl(); // → 'https://api.example.com'
const mutation = useCreate<Post>();
mutation.mutate({ resource: 'posts', variables: { title: '你好' } });
const mutation = useUpdate<Post>();
mutation.mutate({ resource: 'posts', id: 1, variables: { title: '已更新' } });
const mutation = useDelete();
mutation.mutate({ resource: 'posts', id: 1 });
const mutation = useCustomMutation();
mutation.mutate({ url: '/api/posts/publish', method: 'post', values: { ids: [1, 2] } });

批量操作:useCreateMany、useUpdateMany、useDeleteMany

Section titled “批量操作:useCreateMany、useUpdateMany、useDeleteMany”

与单条操作相同的模式,使用数组。

手动刷新缓存的查询:

const invalidate = useInvalidate();
invalidate({ resource: 'posts', invalidates: ['list', 'one'] });

所有变更 Hook 通过 mutationMode 支持三种模式:

模式行为
pessimistic等待服务端响应(默认)
optimistic立即更新 UI,出错时回滚
undoable显示撤销提示,延迟 undoableTimeout 毫秒后再调用服务端
const mutation = useUpdate({ mutationMode: 'undoable', undoableTimeout: 5000 });