TanStack Query
Grabkit returns [data, error, meta]; TanStack Query expects queryFn and mutationFn to throw on failure so the library can set isError, error, and retry behaviour. Use orThrow from the package inside those functions.
Shared API client
Section titled “Shared API client”Create one grab callable per API origin (same pattern as Getting started):
import grabkit, { orThrow } from 'grabkit';
export const grab = grabkit(process.env.NEXT_PUBLIC_API_URL!, { casing: 'camelCase', headers: { // Attach auth in one place, or set per call },});
export { orThrow };Reads with useQuery
Section titled “Reads with useQuery”import { useQuery } from '@tanstack/react-query';import { grab, orThrow } from './api';
type User = { id: string; name: string };
function useUser(id: string) { return useQuery({ queryKey: ['user', id], queryFn: async () => { const [data] = await orThrow(grab<User>(`GET /users/${id}`)); return data; }, enabled: Boolean(id), });}
function Profile({ id }: { id: string }) { const { data, error, isPending } = useUser(id);
if (isPending) return <p>Loading…</p>; if (error) return <p>{error.message}</p>;
return <p>{data.name}</p>;}error in the component is the thrown GrabkitError or GrabkitTransportError from Errors & results.
Writes with useMutation
Section titled “Writes with useMutation”import { useMutation, useQueryClient } from '@tanstack/react-query';import { grab, orThrow } from './api';
function useCreateUser() { const queryClient = useQueryClient();
return useMutation({ mutationFn: async (body: { type: 'users'; name: string }) => { const [data] = await orThrow(grab(`POST /users`, { body })); return data; }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['users'] }); }, });}JSON:API mode requires type on write bodies. See JSON:API (default).
Plain JSON APIs
Section titled “Plain JSON APIs”For GitHub-style APIs, set format: 'json' on the factory (see Plain JSON):
export const grab = grabkit('https://api.github.com', { format: 'json' });Server prefetch (optional)
Section titled “Server prefetch (optional)”On the server, call orThrow(grab(...)) inside queryClient.prefetchQuery, then dehydrate state for the client. Grabkit runs in Node; see Node.js for env and auth patterns.
Related
Section titled “Related”- Migrating from react-grabkit: hooks are no longer bundled; use your data layer instead
- SWR: similar fetcher pattern with
useSWR