Skip to content

异步数据

TanStack Query 的核心是对服务端数据进行管理。下面,我们演示如何在 Model 中实现 CRUD 功能

数据获取:select

如何定义

typescript
@Model()
export class ModelTodo {
  select() {
    return this.$useQueryExisting({
      queryKey: ['select'],
      queryFn: async () => {
        return this.scope.service.todo.select();
      },
    });
  }
}
  • 调用$useQueryExisting 创建 Query 对象
  • 传入 queryKey,确保本地缓存的唯一性
  • 传入 queryFn,在合适的时机调用此函数获取服务端数据

如何使用

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 方法,当数据创建成功后,将selectget 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 方法,当数据创建成功后,将selectget query 设为无效,以便重新获取数据

如何使用

typescript
async deleteTodo(item: ServiceTodoEntity) {
  await this.$$modelTodo.delete().mutateAsync({ id: item.id });
}
  • 调用$$modelTodo.delete()获取 Mutation 对象
    • 重复调用此方法返回的是同一个 Mutation 对象
  • 直接使用 Mutation 对象的方法 mutateAsync 完成异步操作

基于 MIT 许可发布