Pular para o conteúdo principal

useQuery()

Renderização de dados sem o fetch.

Acesse o valor no store de qualquer Schema Queryable, como Entity, All, Collection, Query, Union e Scalar. Campos Lazy também funcionam por meio do accessor .query. Se o valor não existir, retorna undefined.

useQuery() é reativo às mutações de dados, renderizando novamente apenas quando necessário. Retorna undefined quando os dados são Inválidos.

dica

Queries são ótimas companheiras para renderizar com eficiência cálculos agregados, como os que usam groupBy, map, reduce e filter.

Uso​

import { Query } from '@data-client/rest';
import { useQuery } from '@data-client/react';
import { PostResource } from './PostResource';

const queryTotalVotes = new Query(
  PostResource.getList.schema,
  posts => posts.reduce((total, post) => total + post.votes, 0),
);

export default function TotalVotes({ userId }: Props) {
  const totalVotes = useQuery(queryTotalVotes, { userId });
  return (
    <center>
      <small>{totalVotes} votes total</small>
    </center>
  );
}
interface Props {
  userId: number;
}
Resultado

Veja truthiness narrowing para mais informações sobre o tratamento de tipos

Tipos​

function useQuery(
schema: Queryable,
...args: SchemaArgs<typeof schema>
): DenormalizeNullable<typeof endpoint.schema> | undefined;

Queryable​

Schemas Queryable exigem um método queryKey() que retorne algo. Isso inclui Entity, All, Collection, Query, Union e Scalar. Campos Lazy produzem um Queryable por meio do accessor .query.

interface Queryable {
queryKey(
args: readonly any[],
queryKey: (...args: any) => any,
getEntity: GetEntity,
getIndex: GetIndex,
// Must be non-void
): {};
}

Exemplos​

Ordenação e filtragem​

Query fornece acesso programático ao store do Reactive Data Client.

import { All, Query } from '@data-client/rest';
import { useQuery, useFetch } from '@data-client/react';
import { UserResource, User } from './UserResource';

interface Args {
  asc: boolean;
  isAdmin?: boolean;
}
const sortedUsers = new Query(
  new All(User),
  (entries, { asc, isAdmin }: Args = { asc: false }) => {
    let sorted = [...entries].sort((a, b) => a.name.localeCompare(b.name));
    if (isAdmin !== undefined)
      sorted = sorted.filter(user => user.isAdmin === isAdmin);
    if (asc) return sorted;
    return sorted.reverse();
  },
);

function UsersPage() {
  useFetch(UserResource.getList);
  const users = useQuery(sortedUsers, { asc: true });
  if (!users) return <div>No users in cache yet</div>;
  return (
    <div>
      {users.map(user => (
        <div key={user.pk()}>{user.name}</div>
      ))}
    </div>
  );
}
render(<UsersPage />);
Resultado

Total de Todos restantes​

Queries também podem ser usadas para calcular agregados

Explore o exemplo todo-app

Mais demos

Relacionamentos Lazy​

Campos Lazy mantêm os IDs brutos durante a desnormalização do pai. Use .query com useQuery para resolvê-los sob demanda, isolando as renderizações apenas aos componentes que precisam dos dados relacionados.

import { All } from '@data-client/rest';
import { useQuery, useFetch } from '@data-client/react';
import { DepartmentResource, Department } from './Resources';

function BuildingList({ dept }: { dept: Department }) {
  const buildings = useQuery(
    Department.schema.buildings.query,
    dept.buildings,
  );
  if (!buildings) return null;
  return <span>{buildings.map(b => b.name).join(', ')}</span>;
}

function DepartmentsPage() {
  useFetch(DepartmentResource.getList);
  const departments = useQuery(new All(Department));
  if (!departments) return <div>Loading...</div>;
  return (
    <div>
      {departments.map(dept => (
        <div key={dept.pk()}>
          <strong>{dept.name}</strong>: <BuildingList dept={dept} />
        </div>
      ))}
    </div>
  );
}
render(<DepartmentsPage />);
Resultado

Fallbacks de dados​

Neste caso, Ticker é atualizado constantemente por um stream de websocket. No entanto, não existe um fetch em massa/de lista para Ticker, o que o torna ineficiente para obter os preços em uma visualização de lista.

Então, neste caso, podemos buscar uma lista de Stats como fallback, já que ela também tem dados de preço.

Explore o exemplo coin-app

Mais demos