Skip to main content

React hooks

Zodios comes with a Query and Mutation hook helper.
It's a thin wrapper around React-Query but with zodios auto completion and automatic key management. No need to remember your keys anymore.

Zodios query hook also returns an invalidation helper to allow you to reset react query cache easily.

Zodios Hooks instance

When creating an instance or zodios hooks, you need to provide a name that will be used as react-query key prefix and your instance of Zodios Api Client.

new ZodiosHooks(name: string, client: Zodios)

Example

const apiClient = new Zodios(baseUrl, [...]);
const apiHooks = new ZodiosHooks("myAPI", apiClient);

Zodios hooks methods

hooks.use[Alias]

You will usually want to use aliases to call your endpoints. You can define them in the alias option in your API definition endpoint.

query alias:

Query alias hooks will return a QueryResult object from react-query with:

  • the response data and all react-query result properties
  • the generated key
  • the invalidate helper.
function use[Alias](config?: ZodiosRequestOptions, queryOptions: QueryOptions): QueryResult<Response>;

example:

// identical to hooks.useQuery("/users")
const { data: users, isLoading, isError, invalidate, key } = hooks.useGetUsers();

immutable query alias:

function use[Alias](body: Body, config?: ZodiosRequestOptions, queryOptions: QueryOptions): QueryResult<Response>;

example:

// identical to hooks.useImmutableQuery("/users/search")
const { data: users, isLoading, isError } = hooks.useSearchUsers({ name: "John" });
note

Immutable query aliases are only available for post endpoints. you also need to set the immutable option to true in your API definition endpoint if you want alias to use useImmutableQuery hook.

mutation alias

Alias for post, put, patch, delete endpoints:

function use[Alias](config?: ZodiosRequestOptions, queryOptions?: QueryOptions): MutationResult<Response>;

example:

// identical to usePost("/users") or useMutation("post","/users")
const { mutate } = hooks.useCreateUser();

zodios.useQuery

Generic request method that allows to do queries (same as useGet). Query hooks will return a QueryResult object from react-query with:

  • the response data and all react-query result properties
  • the generated key
  • the invalidate helper.
useQuery(path: string, config?: ZodiosRequestOptions, queryOptions?: QueryOptions): QueryResult<Response>;

Example:

const { data: users, isLoading, isError } = hooks.useQuery('/users');
note

check react-query documentation for more informations on QueryResult and QueryOptions.

zodios.useImmutableQuery

Generic request method that allows to do queries on post requests.

useImmutableQuery(path: string, body: Body ,config?: ZodiosRequestOptions, queryOptions?: QueryOptions): QueryResult<Response>;

Example:

const { data: users, isLoading, isError } = hooks.useImmutableQuery('/users/search', { name: "John" });
note

check react-query documentation for more informations on QueryResult and QueryOptions.

zodios.useInfiniteQuery

Generic request method that allows to load pages indefinitly.

useInfiniteQuery(path: string, config?: ZodiosRequestOptions, infiniteQueryOptions?: InfiniteQueryOptions): InfiniteQueryResult<Response>;

Compared to native react-query infinite query, you also need to provide a function named getPageParamList to tell zodios which parameters will be used to paginate. Indeed, zodios needs to know it to be able to generate the correct query key automatically for you.

Example:

  const { data: userPages, isFectching, fetchNextPage } = apiHooks.useInfiniteQuery(
"/users",
{
// request 10 users per page
queries: { limit: 10 },
},
{
// tell zodios to not use page as query key to allow infinite loading
getPageParamList: () => ["page"],
// get next page param has to return the next page as a query or path param
getNextPageParam: (lastPage, pages) => lastPage.nextPage ? {
queries: {
page: lastPage.nextPage,
},
}: undefined;
}
);
note

check react-query infinite query documentation for more informations on InfiniteQueryResult and InfiniteQueryOptions.

zodios.useImmutableInfiniteQuery

Generic request method that allows to search pages indefinitly with post requests.

useImmutableInfiniteQuery(path: string, body: Body ,config?: ZodiosRequestOptions, infiniteQueryOptions?: InfiniteQueryOptions): InfiniteQueryResult<Response>;

Compared to native react-query infinite query, you also need to provide a function named getPageParamList to tell zodios which parameters will be used to paginate. Indeed, zodios needs to know it to be able to generate the correct query key automatically for you.

Example:

  const { data: userPages, isFectching, fetchNextPage } = apiHooks.useImmutableInfiniteQuery(
"/users/search",
{
// search for users named John
name: "John",
// request 10 users per page
limit: 10,
},
undefined,
{
// tell zodios to not use page as query key to allow infinite loading
getPageParamList: () => ["page"],
// get next page param has to return the next page as a query or path param
getNextPageParam: (lastPage, pages) => lastPage.nextPage ? {
body: {
page: lastPage.nextPage,
},
}: undefined;
}
);
note

check react-query infinite query documentation for more informations on InfiniteQueryResult and InfiniteQueryOptions.

zodios.useMutation

Generic request method that allows to do mutations.

useMutation(method: string, path: string, config: ZodiosRequestOptions, reactQueryOptions?: ReactQueryOptions): ReactMutationResult<Response>;

Example:

const { mutate } = hooks.useMutation('post','/users');
note

check react-query documentation for more informations on MutationResult and MutationOptions.

zodios.useGet

Query hooks will return a QueryResult object from react-query with:

  • the response data and all react-query result properties
  • the generated key
  • the invalidate helper.
useGet(path: string, config?: ZodiosRequestOptions, reactQueryOptions?: ReactQueryOptions): ReactQueryResult<Response>;

Example:

const { data: user, isLoading, isError, invalidate, key } = hooks.useGet("/users/:id", { params: { id: 1 } });

zodios.usePost

usePost(path: string, config?: ZodiosRequestOptions, reactQueryOptions?: ReactQueryOptions): ReactMutationResult<Response>;

Example:

const { mutate } = hooks.usePost("/users");

zodios.usePut

usePut(path: string, config?: ZodiosRequestOptions, reactQueryOptions?: ReactQueryOptions): ReactMutationResult<Response>;

Example:

const { mutate } = hooks.usePut("/users/:id", { params: { id: 1 } });

zodios.usePatch

usePatch(path: string, config?: ZodiosRequestOptions, reactQueryOptions?: ReactQueryOptions): ReactMutationResult<Response>;

Example:

const { mutate } = hooks.usePatch("/users/:id", {params: {id: 1}});

zodios.useDelete

useDelete(path: string, config?: ZodiosRequestOptions, reactQueryOptions?: ReactQueryOptions): ReactMutationResult<Response>;

Example:

const { mutate } = hooks.useDelete("/users/:id", { params: {id: 1 }});

Zodios key helpers

Zodios provides some helpers to generate query keys to be used to invalidate cache or to get it directly from cache with 'QueryClient.getQueryData(key)'.

zodios.getKeyByPath

getKeyByPath(method: string, path: string, config?: ZodiosRequestOptions): QueryKey;

Examples:

To get a key for a path endpoint with parameters:

const key = zodios.getKeyByPath('get', '/users/:id', { params: { id: 1 } });
const user = queryClient.getQueryData<User>(key);

To get a key to invalidate a path endpoint for all possible parameters:

const key = zodios.getKeyByPath('get', '/users/:id');
queryClient.invalidateQueries(key);

zodios.getKeyByAlias

getKeyByAlias(alias: string, config?: ZodiosRequestOptions): QueryKey;

Examples:

To get a key for an alias endpoint with parameters:

const key = zodios.getKeyByAlias('getUser', { params: { id: 1 } });
const user = queryClient.getQueryData<User>(key);

To get a key to invalidate an alias endpoint for all possible parameters:

const key = zodios.getKeyByAlias('getUser');
queryClient.invalidateQueries(key);

Bundling

If you are bundling your App with Webpack and with a custom library that embeds @zodios/react or @tanstack/react-query, you need to bundle you library with both esm and cjs support. We recommend using tsup to bundle your library and declare your package.json like this Else, you'll get the following error:

error

Example

users.tsx
import React from "react";
import { Zodios } from "@zodios/core";
import { ZodiosHooks } from "@zodios/react";
import { z } from "zod";

const baseUrl = "https://jsonplaceholder.typicode.com";
const zodios = new Zodios(baseUrl, [...]);
const zodiosHooks = new ZodiosHooks("jsonplaceholder", zodios);

const Users = () => {
const {
data: users,
isLoading,
error,
invalidate: invalidateUsers, // zodios also provides invalidation helpers
key // zodios also returns the generated key
} = zodiosHooks.useQuery("/users"); // or useGetUsers();
const { mutate } = zodiosHooks.useMutation("post", "/users", undefined, {
onSuccess: () => invalidateUsers(),
}); // or .useCreateUser(...);

return (
<>
<h1>Users</h1>
<button onClick={() => mutate({ name: "john doe" })}>add user</button>
{isLoading && <div>Loading...</div>}
{error && <div>Error: {(error as Error).message}</div>}
{users && (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)}
</>
);
};
root.tsx
import { QueryClient, QueryClientProvider } from "react-query";
import { Users } from "./users";

const queryClient = new QueryClient();

export const App = () => {
return (
<QueryClientProvider client={queryClient}>
<Users />
</QueryClientProvider>
);
};