异步数据
TanStack Query 的核心是对服务端数据进行管理。下面,我们演示如何在 Model 中实现 CRUD 功能
- 完整代码示例,请参见:demo-todo
数据获取:select
如何定义
typescript
@Model()
export class ModelTodo {
select() {
return this.$useQueryExisting({
queryKey: ['select'],
queryFn: async () => {
return this.scope.service.todo.select();
},
});
}
}
- 调用$useQueryExisting 创建 Query 对象
- 传入 queryKey,确保本地缓存的唯一性
- 传入 queryFn,在合适的时机调用此函数获取服务端数据
- service.todo.select:参见Api服务
如何使用
typescript
export class RenderTodo {
@Use()
$$modelTodo: ModelTodo;
render() {
return (
<div>
<div>isLoading: {this.$$modelTodo.select().isLoading}</div>
<div>
{this.$$modelTodo.select().data?.map(item => {
return <div>{item.title}</div>;
})}
</div>
</div>
);
}
}
- 注入 Model Bean 实例:$$modelTodo
- 调用$$modelTodo.select()获取 Query 对象
- 重复调用此方法返回的是同一个 Query 对象
- 直接使用 Query 对象中的状态和数据
数据获取:get
如何定义
typescript
@Model()
export class ModelTodo {
get(params?: ServiceTodoGetParams) {
if (!params) return undefined;
return this.$useQueryExisting({
queryKey: ['get', params.id],
queryFn: async () => {
return this.scope.service.todo.get(params);
},
});
}
}
- 调用$useQueryExisting 创建 Query 对象
- 传入 queryKey,确保本地缓存的唯一性
- 由于是单条数据,需要指定条目的关键字段值
- 传入 queryFn,在合适的时机调用此函数获取服务端数据
如何使用
typescript
export class RenderTodo {
render() {
const params = { id: '1' };
const todo = this.$$modelTodo.get(params);
return (
<div>
<div>todo title: {todo?.data?.title}</div>
<div>{todo?.error?.message}</div>
</div>
);
}
}
- 调用$$modelTodo.get()获取 Query 对象
- 重复调用此方法返回的是同一个 Query 对象
- 直接使用 Query 对象中的状态和数据
数据变更:insert
如何定义
typescript
@Model()
export class ModelTodo {
insert() {
return this.$useMutationExisting<void, ServiceTodoIntertParams>({
mutationKey: ['insert'],
mutationFn: async params => {
return this.scope.service.todo.insert(params);
},
onSuccess: () => {
this.$invalidateQueries({ queryKey: ['select'] });
},
});
}
}
- 调用$useMutationExisting 创建 Mutation 对象
- 传入 mutationKey,确保本地缓存的唯一性
- 传入 mutationFn,用于执行变更操作
- 响应 onSuccess 方法,当数据创建成功后,将
select
query 设为无效,以便重新获取数据
如何使用
typescript
async addTodo() {
const todo = {
id: this.app.meta.util.uuid(),
title: this.newTitle,
done: false,
};
await this.$$modelTodo.insert().mutateAsync(todo);
}
- 准备新数据 todo
- 调用$$modelTodo.insert()获取 Mutation 对象
- 重复调用此方法返回的是同一个 Mutation 对象
- 直接使用 Mutation 对象的方法 mutateAsync 完成异步操作
数据变更:update
如何定义
typescript
@Model()
export class ModelTodo {
update() {
return this.$useMutationExisting<void, ServiceTodoUpdateParams>({
mutationKey: ['update'],
mutationFn: async params => {
return this.scope.service.todo.update(params);
},
onSuccess: (_data, params) => {
this.$invalidateQueries({ queryKey: ['select'] });
this.$invalidateQueries({ queryKey: ['get', params.id] });
},
});
}
}
- 调用$useMutationExisting 创建 Mutation 对象
- 传入 mutationKey,确保本地缓存的唯一性
- 传入 mutationFn,用于执行变更操作
- 响应 onSuccess 方法,当数据创建成功后,将
select
和get
query 设为无效,以便重新获取数据
如何使用
typescript
async completeTodo(item: ServiceTodoEntity) {
const todo = { ...item, done: true };
await this.$$modelTodo.update().mutateAsync(todo);
}
- 准备好数据 todo
- 调用$$modelTodo.update()获取 Mutation 对象
- 重复调用此方法返回的是同一个 Mutation 对象
- 直接使用 Mutation 对象的方法 mutateAsync 完成异步操作
数据变更:delete
如何定义
typescript
@Model()
export class ModelTodo {
delete() {
return this.$useMutationExisting<void, ServiceTodoDeleteParams>({
mutationKey: ['delete'],
mutationFn: async params => {
return this.scope.service.todo.delete(params);
},
onSuccess: (_data, params) => {
this.$invalidateQueries({ queryKey: ['select'] });
this.$invalidateQueries({ queryKey: ['get', params.id] });
},
});
}
}
- 调用$useMutationExisting 创建 Mutation 对象
- 传入 mutationKey,确保本地缓存的唯一性
- 传入 mutationFn,用于执行变更操作
- 响应 onSuccess 方法,当数据创建成功后,将
select
和get
query 设为无效,以便重新获取数据
如何使用
typescript
async deleteTodo(item: ServiceTodoEntity) {
await this.$$modelTodo.delete().mutateAsync({ id: item.id });
}
- 调用$$modelTodo.delete()获取 Mutation 对象
- 重复调用此方法返回的是同一个 Mutation 对象
- 直接使用 Mutation 对象的方法 mutateAsync 完成异步操作