@openapi-qraft/react
is a modular TypeScript client designed to facilitate type-safe API requests in React
applications,
leveraging the power of TanStack Query v5. It utilizes a Proxy-based architecture to dynamically generate
hooks with typed parameters, ensuring that your API requests are both type-safe and efficient.
Read the full documentation at openapi-qraft.github.io/openapi-qraft.
- Type-safe API Requests: Utilize TypeScript for type-safe API requests, reducing runtime errors and improving developer experience.
- Modular Design: Customize the utility with a set of callbacks to handle API calls according to your project's needs.
- Integration with TanStack Query v5: Seamlessly integrate with TanStack Query for handling server state, caching, and data synchronization.
- Dynamic Proxy-Based Hooks: Automatically generate React Query hooks for your API endpoints without manual boilerplate.
First, install the core package for your project:
npm install @openapi-qraft/react
If your project doesn't already include @tanstack/react-query
, you'll also need to install it. This package is
essential for handling server state in React applications:
npm install @tanstack/react-query
To get started with OpenAPI Qraft, you need to generate types and service definitions from your OpenAPI Document. These are used to create type-safe hooks and interact with your API.
Run the following command in the root directory of your project using your package manager:
npx @openapi-qraft/cli --plugin tanstack-query-react --plugin openapi-typescript \
--output-dir src/api https://raw.githubusercontent.com/swagger-api/swagger-petstore/master/src/main/resources/openapi.yaml
💡 For stable project maintenance, it's recommended to install the CLI generator as a dev dependency. Read more about installation in the documentation.
Below are examples demonstrating how to use the generated services in your React application with
useQuery
, useMutation
, and useInfiniteQuery
hooks from TanStack Query.
import { requestFn } from '@openapi-qraft/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { createAPIClient } from './api'; // generated by OpenAPI Qraft
const queryClient = new QueryClient();
// Use `createAPIClient(...)` to initialize the API client as needed.
// It's a lightweight 🪶 shortcut for working with TanStack Query 🌴
const api = createAPIClient({
requestFn,
queryClient,
baseUrl: 'https://petstore3.swagger.io/api/v3',
});
function ExamplePetDetails({ petId }: { petId: number }) {
/**
* Executes the request to the API on mount:
* ###
* GET /pet/123456
**/
const {
data: pet,
isPending,
error,
} = api.pet.getPetById.useQuery({
path: { petId },
});
if (isPending) {
return <div>Loading...</div>;
}
if (error) {
return <div>Error: {error.message}</div>;
}
return <div>Pet Name: {pet?.name}</div>;
}
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<ExamplePetDetails petId={123456} />
</QueryClientProvider>
);
}
import { requestFn } from '@openapi-qraft/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { createAPIClient } from './api'; // generated by OpenAPI Qraft
const queryClient = new QueryClient();
const api = createAPIClient({
requestFn,
queryClient,
baseUrl: 'https://petstore3.swagger.io/api/v3',
});
function EntityForm({ entityId }: { entityId: string }) {
const mutation = api.entities.postEntitiesIdDocuments.useMutation({
// ☝️ useMutation() can be used with `undefined` parameters
path: {
entity_id: entityId,
},
header: {
'x-monite-version': '2023-09-01',
},
});
return (
<form
onSubmit={(event) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
/**
* Executes the request`:
* ###
* POST /entities/3e3e-3e3e-3e3e/documents
* x-monite-version: 2023-09-01
*
* {"company_tax_id_verification": ["verification-id"]}
**/
mutation.mutate({
company_tax_id_verification: [
String(formData.get('company_tax_id_verification')),
],
});
}}
>
<input name="company_tax_id_verification" />
<button>Submit</button>
</form>
);
}
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<EntityForm entityId="3e3e-3e3e-3e3e" />
</QueryClientProvider>
);
}
import { requestFn } from '@openapi-qraft/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { createAPIClient } from './api'; // generated by OpenAPI Qraft
const queryClient = new QueryClient();
const api = createAPIClient({
requestFn,
queryClient,
baseUrl: 'https://petstore3.swagger.io/api/v3',
});
/**
* Executes the initial request:
* ###
* GET /posts?limit=10&page=1
**/
function PostList() {
const infiniteQuery = api.posts.getPosts.useInfiniteQuery(
{ query: { limit: 10 } },
{
getNextPageParam: (lastPage, allPages, lastPageParams) => {
if (lastPage.length < 10) return; // if less than 10 items, there are no more pages
return {
query: {
page: Number(lastPageParams.query?.page) + 1,
},
};
},
initialPageParam: {
query: {
page: 1, // will be used in initial request
},
},
}
);
return (
<div>
{infiniteQuery.data?.pages.map((page, pageIndex) => (
<ul key={pageIndex}>
{page.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
))}
<button
onClick={() => {
// ⬇︎ Executes GET /posts?limit=10&page=2
infiniteQuery.fetchNextPage();
}}
>
Load More
</button>
</div>
);
}
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<PostList />
</QueryClientProvider>
);
}
- [x]
useQuery(...)
- [x]
useMutation(...)
- [x]
useInfiniteQuery(...)
- [x]
useQueries(...)
- [x]
useSuspenseQuery(...)
- [x]
useSuspenseInfiniteQuery(...)
- [x]
useSuspenseQueries(...)
- [x]
useIsFetching(...)
- [x]
useMutationState(...)
- [x]
useIsMutating(...)
- [x]
fetchQuery(...)
- [x]
fetchInfiniteQuery(...)
- [x]
prefetchQuery(...)
- [x]
prefetchInfiniteQuery(...)
- [x]
getQueryData(...)
- [x]
getQueriesData(...)
- [x]
setQueryData(...)
- [x]
getQueryState(...)
- [x]
setQueriesData(...)
- [x]
invalidateQueries(...)
- [x]
refetchQueries(...)
- [x]
cancelQueries(...)
- [x]
removeQueries(...)
- [x]
resetQueries(...)
- [x]
isFetching(...)
- [x]
isMutating(...)
- [x]
getQueryKey(...)
- [x]
setInfiniteQueryData(...)
- [x]
getInfiniteQueryKey(...)
- [x]
getInfiniteQueryData(...)
- [x]
getInfiniteQueryState(...)
- [x]
getMutationKey(...)
Contributions are welcome! If you have suggestions or want to improve @openapi-qraft/react
, please feel free to submit
a pull request or open an issue.
@openapi-qraft/react
is licensed under the MIT License. See the LICENSE file for more details.