import { createFileRoute } from "@tanstack/react-router"; import { useSuspenseQuery } from "@tanstack/react-query"; import { useLiveSuspenseQuery, eq, toArray } from "@tanstack/react-db"; import * as v from "valibot"; import { ChapterSplitColumn } from "~/chapters/chapter-split"; import { DemoCard } from "~/demos/components/demo-card"; import { PokedexPagination, PokedexTableResults, PokedexTableSection, } from "~/demos/components/pokedex-table-section"; import { getArticleQueryOptions } from "~/articles/querys"; import { pokemonCollection, typesCollection, pokemonTypesCollection, } from "~/demos/live-query/collections"; import { getPokemonListingQueryLimit, toPokemonListing, } from "~/demos/pokemon-listing/pokemon-listing"; const searchParamsSchema = v.object({ offset: v.optional(v.number(), 0), }); export const Route = createFileRoute("/_chapters/live-query")({ staticData: { routeTitle: "07_live-query", routeSubtitle: "// Electric SQL synced collection", }, ssr: false, validateSearch: searchParamsSchema, context: () => { const liveQueryArticleQueryOptions = getArticleQueryOptions({ slug: "live-query", }); return { liveQueryArticleQueryOptions }; }, loader: async ({ context: { queryClient, liveQueryArticleQueryOptions } }) => { await queryClient.ensureQueryData(liveQueryArticleQueryOptions); }, component: RouteComponent, }); function RouteComponent() { const { offset: currentOffset } = Route.useSearch(); const { liveQueryArticleQueryOptions } = Route.useRouteContext(); const { data: { Article }, } = useSuspenseQuery(liveQueryArticleQueryOptions); return ( } > } /> ); } function PokemonTableContent({ currentOffset }: { currentOffset: number }) { const { data } = useLiveSuspenseQuery( (q) => q .from({ pokemon: pokemonCollection }) .orderBy(({ pokemon }) => pokemon.dexId) .offset(currentOffset) .limit(getPokemonListingQueryLimit()) .select(({ pokemon }) => ({ id: pokemon.id, name: pokemon.name, dexId: pokemon.dexId, types: toArray( q .from({ pokemonType: pokemonTypesCollection }) .join( { type: typesCollection }, ({ pokemonType, type }) => eq(pokemonType.typeId, type.id), "inner", ) .where(({ pokemonType }) => eq(pokemonType.pokemonId, pokemon.id)) .orderBy(({ pokemonType }) => pokemonType.id) .select(({ type }) => ({ name: type.name })), ), })), [currentOffset], ); const listing = toPokemonListing(data, { offset: currentOffset }); return ( } /> ); }