React Query
Learn how to use CallApi with React Query
This guide covers the essential patterns and best practices for using CallApi within React Query, allowing you to use CallApi's many features alongside React Query's caching and synchronization capabilities.
Quick Start
By default, CallApi returns errors as values in the result object instead of throwing them. However, React Query expects either a resolved promise with data or a rejected promise with an error.
You configure callApi to align with that expectation:
import { useQuery } from "@tanstack/react-query";
import { callApi } from "@zayne-labs/callapi";
type Todo = {
completed: boolean;
id: number;
title: string;
};
export const useTodos = () => {
return useQuery({
queryKey: ["todos"],
queryFn: () => {
return callApi<Todo[], false>("/todos", {
throwOnError: true,
resultMode: "onlyData",
});
},
});
};Configuration Options
The key options for React Query integration include:
throwOnError: true- Makes CallApi throw errors instead of returning them in the result objectresultMode: "onlyData"- Returns just the data property with its exact type, perfect for React Query
These settings ensure CallApi behaves exactly like React Query expects: throwing errors for failures and returning clean data for successes.
Centralized Configuration
import { createFetchClient } from "@zayne-labs/callapi";
export const callApiForQuery = createFetchClient({
baseURL: "https://api.example.com",
// Default to React Query compatible settings
throwOnError: true,
resultMode: "onlyData",
});
// Use the configured client in queries
export const useTodos = () => {
return useQuery({
queryKey: ["todos"],
queryFn: () => callApiForQuery<Todo[]>("/todos"),
});
};Data Inference via typescript
Option 1: Schema Validation (Recommended)
Using validation libraries like Zod provides both runtime safety and automatic type inference:
import { useQuery } from "@tanstack/react-query";
import { callApi } from "@zayne-labs/callapi";
import { z } from "zod";
const todosSchema = z.array(
z.object({
id: z.number(),
title: z.string(),
completed: z.boolean(),
})
);
export const useTodos = () => {
return useQuery({
queryKey: ["todos"],
queryFn: () => {
return callApi("/todos", {
schema: { data: todosSchema },
throwOnError: true,
resultMode: "onlyData",
});
},
});
};Option 2: Manual Type Specification
import { useQuery } from "@tanstack/react-query";
import { callApi } from "@zayne-labs/callapi";
type Todo = {
completed: boolean;
id: number;
title: string;
};
export const useTodos = () => {
return useQuery({
queryKey: ["todos"],
queryFn: () => {
// Pass `false` as second generic to signal errors will be thrown allow callApi to return the expected type
// This is needed due to TypeScript limitations with partial generic inference
// See: https://github.com/microsoft/TypeScript/issues/26242
return callApi<Todo[], false>("@get/todos", {
throwOnError: true,
resultMode: "onlyData",
});
},
});
};Last updated on