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.
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; }
Veja truthiness narrowing para mais informações sobre o tratamento 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
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 />);
Total de Todos restantes
Queries também podem ser usadas para calcular agregados
Explore o exemplo todo-app
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 />);
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