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>
);
};