Saltar al contenido principal

useQuery()

Renderizado de datos sin el fetch.

Accede al valor en el store de cualquier Queryable Schema; como Entity, All, Collection, Query, Union y Scalar. Los campos Lazy también funcionan mediante su accesor .query. Si el valor no existe, devuelve undefined.

useQuery() reacciona a las mutaciones de datos; vuelve a renderizar solo cuando es necesario. Devuelve undefined cuando los datos son Invalid.

consejo

Las Queries son un gran complemento para renderizar de forma eficiente cálculos agregados, como los que usan groupBy, map, reduce y 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▶

Consulta truthiness narrowing para más información sobre el manejo de tipos

Tipos​

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

Queryable​

Los schemas Queryable requieren un método queryKey() que devuelva algo. Entre ellos están Entity, All, Collection, Query, Union y Scalar. Los campos Lazy producen un Queryable mediante su accesor .query.

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

Ejemplos​

Ordenación y filtrado​

Query proporciona acceso programático al store de 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 tareas pendientes​

Las Queries también se pueden usar para calcular agregados

Explora el ejemplo todo-app

More Demos

Relaciones Lazy​

Los campos Lazy conservan los IDs sin resolver durante la desnormalización del padre. Usa .query con useQuery para resolverlos bajo demanda, limitando los re-renderizados únicamente a los componentes que necesitan los datos 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▶

Datos de respaldo​

En este caso, Ticker se actualiza constantemente desde un flujo de websocket. Sin embargo, no existe un fetch masivo/de lista para Ticker, lo que hace ineficiente obtener los precios en una vista de lista.

Así que, en este caso, podemos obtener una lista de Stats como respaldo, ya que también contiene datos de precios.

Explora el ejemplo coin-app

More Demos