Query
Query fornece acesso programático ao cache do Reactive Data Client, mantendo
o mesmo alto desempenho e as mesmas garantias de igualdade referencial esperados do Reactive Data Client.
Query pode ser renderizado usando o hook de consulta por schema useQuery()
Membros de Query
schema
Schema usado para obter/desnormalizar dados do cache do Reactive Data Client.
Aceita qualquer schema Queryable: Entity, All, Collection, Query,
Union, Scalar e schemas Object para fazer join de várias entities.
Campos Lazy produzem um Queryable por meio do acessor .query.
process(entries, ...args)
Recebe a resposta (desnormalizada) como entries, além dos argumentos, e retorna a nova resposta para uso com useQuery
Uso
Mantendo a ordenação após criações
import { Collection, Entity, Query, RestEndpoint } from '@data-client/rest'; export class Post extends Entity { id = ''; title = ''; group = ''; author = ''; } export const getPosts = new RestEndpoint({ path: '/:group/posts', searchParams: {} as { orderBy?: string; author?: string }, schema: new Query( new Collection([Post], { nonFilterArgumentKeys: /orderBy/, }), (posts, { orderBy } = {}) => { if (orderBy) { return [...posts].sort((a, b) => a[orderBy].localeCompare(b[orderBy]), ); } return posts; }, ), });
Agregados
[{"id":"123","name":"Jim"},{"id":"456","name":"Jane"},{"id":"777","name":"Albatras","isAdmin":true}]
import { All, Query } from '@data-client/rest'; import { useQuery, useFetch } from '@data-client/react'; import { UserResource, User } from './resources/User'; const countUsers = new Query( new All(User), (entries, { isAdmin } = {}) => { if (isAdmin !== undefined) return entries.filter(user => user.isAdmin === isAdmin).length; return entries.length; }, ); function UsersPage() { useFetch(UserResource.getList); const userCount = useQuery(countUsers); const adminCount = useQuery(countUsers, { isAdmin: true }); if (userCount === undefined) return <div>No users in cache yet</div>; return ( <div> <div>Total users: {userCount}</div> <div>Total admins: {adminCount}</div> </div> ); } render(<UsersPage />);
Reorganizando dados com agregações groupBy
import { Query } from '@data-client/rest'; import { useQuery, useFetch, useSuspense } from '@data-client/react'; import { TodoResource } from './resources/Todo'; import { UserResource } from './resources/User'; import TodoByUser from './TodoByUser'; const groupTodoByUser = new Query( TodoResource.getList.schema, todos => Object.groupBy(todos, todo => todo.userId), ); function TodosPage() { useFetch(UserResource.getList); useSuspense(TodoResource.getList); useSuspense(UserResource.getList); const todosByUser = useQuery(groupTodoByUser); if (!todosByUser) return <div>Todos not found</div>; return ( <div> {Object.keys(todosByUser).slice(5).map(userId => ( <TodoByUser key={userId} userId={userId} todos={todosByUser[userId]} /> ))} </div> ); } render(<TodosPage />);
Joins com Object Schema
Query pode receber Object Schemas, permitindo joins entre vários tipos de entity. Isso permite combinar dados de diferentes entities em uma única query.
{"product_id":"BTC-USD","price":45000}
{"product_id":"BTC-USD","last":44950}
import { Query } from '@data-client/rest'; import { useQuery, useFetch } from '@data-client/react'; import { TickerResource, Ticker } from './resources/Ticker'; import { StatsResource, Stats } from './resources/Stats'; // Join Ticker and Stats by product_id const queryPrice = new Query( { ticker: Ticker, stats: Stats }, ({ ticker, stats }) => ticker?.price ?? stats?.last, ); function PriceDisplay({ productId }: { productId: string }) { useFetch(TickerResource.get, { product_id: productId }); useFetch(StatsResource.get, { product_id: productId }); const price = useQuery(queryPrice, { product_id: productId }); if (price === undefined) return <div>Loading...</div>; return <div>Price: ${price}</div>; } render(<PriceDisplay productId="BTC-USD" />);
Joins de fallback
Neste caso, Ticker é atualizado constantemente a partir de um stream de websocket. No entanto, não há fetch
em lote/lista para Ticker - o que torna ineficiente obter os preços em uma visualização de lista.
Portanto, 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