useServerQuery

Wraps a server function for query-style (read) usage. Automatically executes on mount and re-fetches when the cache key changes. Supports stale-time caching and manual refetching.

Import

import { useServerQuery } from "catmint/hooks";

Signature

function useServerQuery<TInput, TOutput>(
  fn: (input: TInput) => Promise<TOutput>,
  opts: ServerQueryOptions<TInput>,
): ServerQueryState<TOutput>;
interface ServerQueryOptions<TInput> {
  input: TInput;
  key?: unknown[];
  enabled?: boolean;
  staleTime?: number;
}

interface ServerQueryState<TOutput> {
  data: TOutput | undefined;
  error: Error | undefined;
  loading: boolean;
  refetch: () => Promise<void>;
}

Parameters

ParameterTypeRequiredDescription
fn(input: TInput) => Promise<TOutput>YesA server function to call as a query.
optsServerQueryOptions<TInput>YesQuery configuration (see below).

ServerQueryOptions

PropertyTypeRequiredDescription
inputTInputYesThe input to pass to the server function.
keyunknown[]NoCache key array. When the serialized key changes, the query re-fetches. Also used for stale-time caching.
enabledbooleanNoWhether the query should auto-execute. Defaults to true. Set to false to defer execution.
staleTimenumberNoTime in milliseconds that cached data is considered fresh. While fresh, the query returns cached data without re-fetching.

Return Value

PropertyTypeDescription
dataTOutput | undefinedThe query result, or undefined if not yet loaded.
errorError | undefinedThe most recent error, or undefined.
loadingbooleantrue while the query is in flight.
refetch() => Promise<void>Manually re-fetch the data, bypassing the stale-time cache.

Examples

Basic query

// UserProfile.client.tsx
import { useServerQuery } from "catmint/hooks";
import { getUser } from "./queries";

function UserProfile({ userId }: { userId: string }) {
  const { data, loading, error } = useServerQuery(getUser, {
    input: { id: userId },
    key: [userId],
  });

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;
  if (!data) return null;

  return <h1>{data.name}</h1>;
}

With stale-time caching

const { data } = useServerQuery(getProducts, {
  input: { category: "shoes" },
  key: ["products", "shoes"],
  staleTime: 60_000, // Cache for 1 minute
});

Conditional fetching

const { data } = useServerQuery(getOrderDetails, {
  input: { orderId },
  key: [orderId],
  enabled: !!orderId, // Only fetch when orderId is available
});

Manual refetch

const { data, refetch } = useServerQuery(getNotifications, {
  input: {},
  key: ["notifications"],
});

return (
  <div>
    <button onClick={() => refetch()}>Refresh</button>
    {data?.map((n) => (
      <Notification key={n.id} {...n} />
    ))}
  </div>
);

See Also