Skip to content

Commit b775acf

Browse files
committed
feat: update documentation for context-based API client usage and configuration
1 parent 3e08ed0 commit b775acf

3 files changed

Lines changed: 81 additions & 51 deletions

File tree

website/docs/codegen/cli/redocly-config.mdx

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,47 @@ apis:
242242
- getInfiniteQueryKey
243243
```
244244

245-
::::info Context-based createAPIClient
246-
`context:<ContextName>` is a must-have for React Compiler compatibility because it keeps generated hooks static
247-
(API client can be created outside React components).
248-
Need full setup and runtime patterns? See
249-
[Context-based API Client](../openapi/create-api-client-function/context-api-client.mdx).
250-
::::
245+
#### Using Context for React Compiler Compatibility
246+
247+
The `context` option generates a React Context that provides `queryClient`, `requestFn`, and `baseUrl` to the API client.
248+
This allows you to create the client **outside of React components**, making hooks static and compatible with React Compiler.
249+
250+
```yaml
251+
apis:
252+
main:
253+
root: ./openapi.json
254+
x-openapi-qraft:
255+
plugin:
256+
tanstack-query-react: true
257+
openapi-typescript: true
258+
output-dir: src/api
259+
create-api-client-fn:
260+
# React API client with Context support
261+
createAPIClient:
262+
context: APIClientContext # Generate APIClientContext React Context
263+
callbacks:
264+
- useQuery
265+
- useMutation
266+
- setQueryData
267+
- getQueryData
268+
- getQueryKey
269+
- getInfiniteQueryKey
270+
```
271+
272+
With this configuration, you can create the API client outside of components:
273+
274+
```tsx
275+
import { createAPIClient, APIClientContext } from './api';
276+
277+
// Create outside component - hooks are static and React Compiler compatible
278+
const api = createAPIClient();
279+
280+
function MyComponent() {
281+
// Hooks read queryClient, requestFn, baseUrl from APIClientContext
282+
const { data } = api.pets.getPets.useQuery();
283+
return <div>{data?.length} pets</div>;
284+
}
285+
```
286+
287+
For detailed documentation on using Context-based API clients, see the
288+
[Context-based API Client](../openapi/create-api-client-function/context-api-client.mdx) documentation.

website/docs/codegen/openapi/create-api-client-function/index.mdx

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -148,51 +148,30 @@ the necessary `requestFn`, `baseUrl` and `queryClient` for React Hooks.
148148
```
149149
</TabItem>
150150
<TabItem value="multiple-api-versions" label={<span style={{verticalAlign: 'middle'}}>Multiple API versions and <em>React <code>Context</code></em></span>}>
151-
In this example, we create multiple API clients that manage two different API versions, each with its own `QueryClient`.
152-
This approach mounts and unmounts `QueryClient` instances during the lifecycle of the application.
151+
This example demonstrates how to use multiple API clients with React Context. With the `context:` option
152+
in CLI, you can generate an API client that retrieves `queryClient`, `requestFn`, and `baseUrl` from
153+
React Context at render time.
153154

154-
This setup is particularly useful when you need to work with different API versions simultaneously, or when you're in the process
155-
of migrating from one API version to another.
155+
:::tip React Compiler Compatibility
156+
Creating the API client **outside of the component** with the `context:` option makes hooks static,
157+
allowing React Compiler to optimize them. If you create the client inside `useMemo`, hooks become
158+
dynamic and cannot be optimized by React Compiler.
159+
:::
156160

157161
```tsx title="src/MultipleAPIClientsApp.tsx"
158-
import { createAPIClient as createAPIClientV1Basic } from './api-v1'; // generated by OpenAPI Qraft CLI (1️⃣)
159-
import { createAPIClient as createAPIClientV2Basic } from './api-v2'; // generated by OpenAPI Qraft CLI (2️⃣)
160-
import { requestFn, type CreateAPIBasicClientOptions, type CreateAPIQueryClientOptions } from '@openapi-qraft/react';
161-
import { createContext, useContext, useMemo, useEffect, type ReactNode} from "react";
162+
import { createAPIClient as createAPIClientV1, APIClientContextV1 } from './api-v1'; // generated with context:APIClientContextV1
163+
import { createAPIClient as createAPIClientV2, APIClientContextV2 } from './api-v2'; // generated with context:APIClientContextV2
164+
import { requestFn } from '@openapi-qraft/react';
165+
import { useEffect, useState, type ReactNode } from "react";
162166
import { QueryClient } from '@tanstack/react-query'
163167

164-
// Hypothetical legacy API Client
165-
function createAPIClientV1(options: CreateAPIQueryClientOptions) {
166-
return createAPIClientV1Basic(options);
167-
}
168-
169-
// New version API Client
170-
function createAPIClientV2(options: CreateAPIQueryClientOptions) {
171-
return createAPIClientV2Basic(options);
172-
}
173-
174-
const MultipleAPIClientsContext = createContext<{
175-
apiV1: ReturnType<typeof createAPIClientV1>; // 1️⃣
176-
apiV2: ReturnType<typeof createAPIClientV2>; // 2️⃣
177-
}>(null!);
168+
// ⬇︎ Create API clients OUTSIDE of the component - hooks are static and React Compiler compatible
169+
const apiV1 = createAPIClientV1(); // Uses APIClientContextV1 for options
170+
const apiV2 = createAPIClientV2(); // Uses APIClientContextV2 for options
178171

179172
export default function MultipleAPIClientsApp({ children }: { children: ReactNode }) {
180-
const queryClient1 = useMemo(() => new QueryClient(), []);
181-
const queryClient2 = useMemo(() => new QueryClient(), []);
182-
183-
// Hypothetical legacy API Client without Query Client feature
184-
const apiV1 = useMemo(() => createAPIClientV1({
185-
requestFn,
186-
queryClient: queryClient1,
187-
baseUrl: 'https://api.sandbox.monite.com/v1',
188-
}), [queryClient1]);
189-
190-
// New version API Client with the modern features
191-
const apiV2 = useMemo(() => createAPIClientV2({
192-
requestFn,
193-
queryClient: queryClient2,
194-
baseUrl: 'https://api.sandbox.monite.com/v2',
195-
}), [queryClient2]);
173+
const [queryClient1] = useState(() => new QueryClient());
174+
const [queryClient2] = useState(() => new QueryClient());
196175

197176
useEffect(() => {
198177
queryClient1.mount();
@@ -204,18 +183,24 @@ the necessary `requestFn`, `baseUrl` and `queryClient` for React Hooks.
204183
}, [queryClient1, queryClient2]);
205184

206185
return (
207-
<MultipleAPIClientsContext.Provider value={{ apiV1, apiV2 }}>
208-
{children}
209-
</MultipleAPIClientsContext.Provider>
186+
<APIClientContextV1.Provider value={{ requestFn, queryClient: queryClient1, baseUrl: 'https://api.example.com/v1' }}>
187+
<APIClientContextV2.Provider value={{ requestFn, queryClient: queryClient2, baseUrl: 'https://api.example.com/v2' }}>
188+
{children}
189+
</APIClientContextV2.Provider>
190+
</APIClientContextV1.Provider>
210191
);
211192
}
212193

213-
function YourComponents() {
214-
const { apiV1, apiV2 } = useContext(MultipleAPIClientsContext);
194+
function YourComponent() {
195+
// ⬇︎ Use hooks directly - they read options from Context
196+
const { data: v1Data } = apiV1.pets.getPets.useQuery();
197+
const { data: v2Data } = apiV2.pets.getPets.useQuery();
215198

216-
// Use `apiV1` and `apiV2` as needed
217-
// ...
199+
return <div>...</div>;
218200
}
219201
```
202+
203+
For more details on configuring and using the Context-based API client, see the
204+
[Context-based API Client](./context-api-client.mdx) documentation.
220205
</TabItem>
221206
</Tabs>

website/docs/codegen/openapi/index.mdx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,10 @@ It is possible to use multiple plugins at the same time. For example, `--plugin
205205
- `all` - include all available callbacks (useQuery, useMutation, setQueryData, etc.)
206206
- `none` - don't include any callbacks by default (they must be specified when calling the function)
207207
- `useQuery,useMutation,...` - list of specific callbacks to include
208+
- `context:<ContextName>` - Generate a React Context that provides `queryClient`, `requestFn`, and `baseUrl` to the API client.
209+
When the API client is created without options, it reads these values from the Context at render time.
210+
This enables creating the client **outside of React components**, making hooks static and compatible with React Compiler.
211+
See [Context-based API Client](./create-api-client-function/context-api-client.mdx) for detailed documentation.
208212
- **Examples:**
209213
- `--create-api-client-fn createAPIClient services:all callbacks:all` - creates the `createAPIClient()` function that
210214
includes all services and all callbacks by default (_default_ behavior)
@@ -213,6 +217,9 @@ It is possible to use multiple plugins at the same time. For example, `--plugin
213217
building a **minimal bundle size** client where you explicitly control which services and callbacks to include.
214218
- `--create-api-client-fn createCustomClient filename:create-custom-api services:none callbacks:setQueryData,getQueryData` - creates
215219
the `createCustomClient()` function in the `create-custom-api.ts` file with no default services and only `setQueryData()` and `getQueryData()` callbacks
220+
- `--create-api-client-fn createAPIClient context:APIClientContext callbacks:useQuery,useMutation` - creates
221+
the `createAPIClient()` function with a generated `APIClientContext` React Context. When called without options,
222+
the client reads `queryClient`, `requestFn`, and `baseUrl` from the Context
216223

217224
::::tip
218225
When generating multiple API client functions with different parameters, it might be more convenient to use a configuration file

0 commit comments

Comments
 (0)