UNPKG

@openapi-qraft/react

Version:

OpenAPI client for React, providing type-safe requests and dynamic TanStack Query React Hooks via a modular, Proxy-based architecture.

289 lines (238 loc) 10.6 kB
# @openapi-qraft/react `@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](https://openapi-qraft.github.io/openapi-qraft/). ## Features - **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](https://tanstack.com/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. ## Installation First, install the core package for your project: ```bash 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: ```bash npm install @tanstack/react-query ``` ## Getting Started 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. ### 1. Generate OpenAPI Types & Services Run the following command in the root directory of your project using your package manager: ```bash 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](https://openapi-qraft.github.io/openapi-qraft/docs/getting-started/installation). ### 2. Use the generated services in your React application Below are examples demonstrating how to use the generated services in your React application with `useQuery`, `useMutation`, and `useInfiniteQuery` hooks from [TanStack Query](https://tanstack.com/query/latest). #### Example with `useQuery()` ```tsx title="src/App.tsx" 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> ); } ``` #### Example with `useMutation()` ```tsx title="src/App.tsx" 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> ); } ``` #### Example with `useInfiniteQuery()` ```tsx title="src/PostList.tsx" 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> ); } ``` ## Supported Hooks - [x] [`useQuery(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useQuery) - [x] [`useMutation(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useMutation) - [x] [`useInfiniteQuery(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useInfiniteQuery) - [x] [`useQueries(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useQueries) - [x] [`useSuspenseQuery(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useSuspenseQuery) - [x] [`useSuspenseInfiniteQuery(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useSuspenseInfiniteQuery) - [x] [`useSuspenseQueries(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useSuspenseQueries) - [x] [`useIsFetching(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useIsFetching) - [x] [`useMutationState(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useMutationState) - [x] [`useIsMutating(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useIsMutating) ## `QueryClient` methods - [x] [`fetchQuery(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/fetchQuery) - [x] [`fetchInfiniteQuery(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/fetchInfiniteQuery) - [x] [`prefetchQuery(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/prefetchQuery) - [x] [`prefetchInfiniteQuery(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/prefetchInfiniteQuery) - [x] [`getQueryData(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/getQueryData) - [x] [`getQueriesData(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/getQueriesData) - [x] [`setQueryData(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/setQueryData) - [x] [`getQueryState(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/getQueryState) - [x] [`setQueriesData(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/setQueriesData) - [x] [`invalidateQueries(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/invalidateQueries) - [x] [`refetchQueries(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/refetchQueries) - [x] [`cancelQueries(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/cancelQueries) - [x] [`removeQueries(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/removeQueries) - [x] [`resetQueries(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/resetQueries) - [x] [`isFetching(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/isFetching) - [x] [`isMutating(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/isMutating) ## Qraft Utility Functions - [x] [`getQueryKey(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/getQueryKey) - [x] [`setInfiniteQueryData(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/setInfiniteQueryData) - [x] [`getInfiniteQueryKey(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/getInfiniteQueryKey) - [x] [`getInfiniteQueryData(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/getInfiniteQueryData) - [x] [`getInfiniteQueryState(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/getInfiniteQueryState) - [x] [`getMutationKey(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/getMutationKey) ## Contributing 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. ## License `@openapi-qraft/react` is licensed under the MIT License. See the LICENSE file for more details.