This package is related to the Typoas project.
This package provides a set of hook factories to interact with a generated Typoas client in a React application with react-query
.
This dependency should be added into your dependencies.
# @typoas/react-query depends on @tanstack/react-query and @typoas/runtime (peer dependencies)
yarn add @typoas/react-query @tanstack/react-query @typoas/runtime
First, you will need to add the ApiContextProvider
to your react application:
import { ApiContextProvider } from '@typoas/react-query';
import { createContext } from './generated/client';
const client = createContext();
export function App() {
return (
<ApiContextProvider client={client}>
<MyComponent />
</ApiContextProvider>
);
}
Once the ApiContextProvider
is added, you can use one of the hook factories to interact with your generated client:
import { createQueryHook } from '@typoas/react-query';
import { findPetsByStatus } from './generated/client';
const useFindPetsByStatus = createQueryHook(findPetsByStatus, {
// Base options used for all queries created with this hook
});
export function MyComponent() {
const { data, isLoading } = useFindPetsByStatus({
// These options are typed based on the operation's parameters
// All react-query options are supported except for 'queryFn'
queryKey: [{ status: 'available' }],
});
if (isLoading) {
return <div>Loading...</div>;
}
return (
<ul>
{data.map((pet) => (
<li key={pet.id}>{pet.name}</li>
))}
</ul>
);
}
Similar as the createQueryHook
, supporting infinite queries.
import { createQueryHook } from '@typoas/react-query';
import { findPetsByStatus } from './generated/client';
const useFindPetsByStatus = createInfiniteQueryHook(findPetsByStatus, {
initialPageParam: { page: 1 },
getNextPageParam: (lastPage, allPages) => {
if (allPages.length === 1) {
return { page: 2 };
}
return undefined;
},
});
export function MyComponent() {
const { data, isLoading } = useFindPetsByStatus({
// These options are typed based on the operation's parameters
// All react-query options are supported except for 'queryFn'
queryKey: [{ status: 'available' }],
});
if (isLoading) {
return <div>Loading...</div>;
}
return (
<ul>
{data.pages.map((page) =>
page.map((pet) => <li key={pet.id}>{pet.name}</li>),
)}
</ul>
);
}
Mutation are also supported:
import { useCallback } from 'react';
import { createQueryHook } from '@typoas/react-query';
import { addPet } from './generated/client';
const useAddPetMutation = createMutationHook(addPet, {});
export function MyComponent() {
const mutation = useAddPetMutation({});
const onClick = useCallback(() => {
mutation.mutate([
{}, // Path params
{ id: 1, name: 'Rufus', status: 'available', photoUrls: [] }, // Body
]);
}, [mutation.mutate]);
return <button onClick={onClick}></button>;
}
Sometimes you may need to use queryClient.setQueryData
or queryClient.invalidateQueries
with a query hook.
In this case, you can use the getQueryFunctionKey
function to get the queryKey matching the query:
import {
getQueryFunctionKey,
createMutationHook,
createQueryHook,
} from '@typoas/react-query';
import { findPetsByStatus, addPet } from './generated/client';
const useAddPetMutation = createMutationHook(addPet, {
onMutate() {
queryClient.invalidateQueries({
queryKey: [getQueryFunctionKey(findPetsByStatus)],
});
},
});
const useFindPetsByStatus = createQueryHook(findPetsByStatus, {});
Each hook factory accepts a second argument which is the base options for the query/mutation. This also allows 2 additional options:
fetcherData
: Object to be passed to the Typoas fetchersuccessStatus
: Status code to consider the request as successful (default: 2XX, same as theok
function in@typoas/runtime
)
Note that fetcherData
can also be passed in the hook options (will override the base one if provided).
If you need, you can also use the useApiContext
hook to access the client directly:
import { useEffect } from 'react';
import { useApiContext } from '@typoas/react-query';
import { addPet } from './generated/client';
// Must be used as a child of the ApiContextProvider
export function MyComponent() {
const ctx = useApiContext();
// Use the client
useEffect(() => {
addPet(
ctx,
{},
{ id: 1, name: 'Rufus', status: 'available', photoUrls: [] },
);
}, []);
return <div></div>;
}