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.
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; }
Consulta truthiness narrowing para más información sobre el manejo de tipos
Tipos
- Type
- With Generics
function useQuery(
schema: Queryable,
...args: SchemaArgs<typeof schema>
): DenormalizeNullable<typeof endpoint.schema> | undefined;
function useQuery<S extends Queryable>(
schema: S,
...args: SchemaArgs<S>
): DenormalizeNullable<S> | 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 />);
Total de tareas pendientes
Las Queries también se pueden usar para calcular agregados
Explora el ejemplo todo-app
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 />);
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