Query
Query ofrece acceso programático a la caché de Reactive Data Client manteniendo
el mismo alto rendimiento y las mismas garantías de igualdad referencial que se esperan de Reactive Data Client.
Query se puede renderizar usando la búsqueda por schema con el hook useQuery()
Miembros de Query
schema
Schema usado para recuperar y desnormalizar datos de la caché de Reactive Data Client.
Acepta cualquier schema Queryable: Entity, All, Collection, Query,
Union, Scalar y schemas de Object para unir varias entidades.
Los campos Lazy producen un Queryable mediante su acceso .query.
process(entries, ...args)
Recibe la respuesta (desnormalizada) como entries, junto con los argumentos, y devuelve la nueva respuesta para usar con useQuery
Uso
Mantener el orden tras crear elementos
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 />);
Reorganizar datos con agregaciones 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 />);
Uniones con Object Schema
Query puede recibir Object Schemas, lo que permite unir varios tipos de entidad. Esto te permite combinar datos de distintas entidades en una sola consulta.
{"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" />);
Uniones de reserva
En este caso Ticker se actualiza constantemente desde un stream de websocket. Sin embargo, no existe un fetch masivo o de lista
para Ticker, lo que lo hace ineficiente para obtener los precios en una vista de lista.
Así que en este caso podemos obtener una lista de Stats como alternativa, ya que también contiene datos de precios.
Explora el ejemplo coin-app