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
Store▶

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
Store▶

Total de Todos restantes​

Queries também podem ser usadas para calcular agregados

Explore o exemplo todo-app

More 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
Store▶

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

More Demos