React hooks

Use @hypequery/react to generate type-safe hooks (useQuery, useMutation) backed by TanStack Query. Bring your existing defineServe API types and wire them into your React app without duplicating schemas.

Installation

npm install @hypequery/react @tanstack/react-query

Peer dependencies: react@^18, @tanstack/react-query@^5.

Setup

Use InferApiType to automatically extract types from your API definition:

// lib/analytics.ts
import { createHooks } from '@hypequery/react';
import { InferApiType } from '@hypequery/serve';
import type { api } from '@/analytics/queries';

// Automatic type inference - no manual type definition needed!
type Api = InferApiType<typeof api>;

export const { useQuery, useMutation } = createHooks<Api>({
  baseUrl: '/api', // where your hypequery routes live
});

This eliminates the need to manually define and maintain a separate type for your API.

Option 2: Manual Type Definition

If you prefer to manually define your API types:

// lib/analytics.ts
import { createHooks } from '@hypequery/react';

type Api = {
  weeklyRevenue: {
    input: { startDate: string };
    output: { total: number };
  };
  // ... other queries
};

export const { useQuery, useMutation } = createHooks<Api>({
  baseUrl: '/api',
});

Wrap your app:

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient();

export function AppProviders({ children }: { children: React.ReactNode }) {
  return (
    <QueryClientProvider client={queryClient}>
      {children}
    </QueryClientProvider>
  );
}

useQuery

const { data, error, isLoading } = useQuery('weeklyRevenue', {
  startDate: '2025-01-01',
});
  • name is one of your API keys
  • input matches the endpoint’s inputSchema
  • Options mirror TanStack Query (staleTime, enabled, etc.)

useMutation

const rebuild = useMutation('rebuildMetrics');
rebuild.mutate({ force: true });

Mutations share the same typed input/output data.

HTTP Method Configuration

By default, hooks issue GET requests (matching the default route method). Override them per query when you need POST, PUT, etc.:

import { createHooks } from '@hypequery/react';
import { InferApiType } from '@hypequery/serve';
import type { api } from '@/analytics/queries';

type Api = InferApiType<typeof api>;

export const { useQuery, useMutation } = createHooks<Api>({
  baseUrl: '/api',
  config: {
    weeklyRevenue: { method: 'GET' },    // Read-only queries
    tripStats: { method: 'GET' },
    rebuildMetrics: { method: 'POST' },  // Write operations
  },
});

Advanced: Auto-config from Server

You don’t have to maintain the verbs manually—@hypequery/serve can tell the client which HTTP method each route uses.

Option A – share the server module (Next.js / Remix):

When your React code can import the server bundle (e.g., Next.js App Router), just pass api directly:

import { createHooks } from '@hypequery/react';
import { InferApiType } from '@hypequery/serve';
import { api } from '@/analytics/queries';

type Api = InferApiType<typeof api>;

export const { useQuery, useMutation } = createHooks<Api>({
  baseUrl: '/api/hypequery',
  api, // method metadata is extracted automatically
});

Option B – expose a config endpoint (SPAs / Vite):

If your frontend can’t import the server module, publish the config once and hydrate createHooks with it:

// app/api/hypequery-config/route.ts
import { extractClientConfig } from '@hypequery/serve';
import { api } from '@/analytics/queries';

export function GET() {
  return Response.json(extractClientConfig(api));
}
// lib/analytics.ts
import { createHooks } from '@hypequery/react';
import { InferApiType } from '@hypequery/serve';
import type { api } from '@/analytics/queries';

type Api = InferApiType<typeof api>;

let hooksPromise: Promise<ReturnType<typeof createHooks<Api>>> | null = null;

export function getHypequeryHooks() {
  if (!hooksPromise) {
    hooksPromise = fetch('/api/hypequery-config')
      .then((res) => res.json())
      .then((config) =>
        createHooks<Api>({ baseUrl: '/api/hypequery', config })
      );
  }
  return hooksPromise;
}

Call await getHypequeryHooks() once during app bootstrap (e.g., inside a top-level provider) and reuse the returned useQuery/useMutation instances throughout your app.

Advanced options

Both hooks accept the underlying TanStack options, so you can control staleTime, retries, invalidation, manual queryClient access, etc.

Error handling

Errors bubble through TanStack Query’s error state. Validation errors from hypequery endpoints arrive as structured JSON (status code + body). Network failures throw standard fetch errors.

When to use it

  • SPA dashboards needing cached queries
  • Next.js / Remix apps already using TanStack Query
  • Agents or components calling hypequery APIs inline

If you don’t need React hooks, you can call api.execute directly on the server or use the HTTP API as-is.