Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions docs/openapi-react-query/get-key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
title: getKey
---
# {{ $frontmatter.title }}

The `getKey` method allows you to generate a cache key consistent with the `useQuery` and `useMutation` methods. This method is useful if you need to invalidate a key in the `queryClient`.

::: tip
You can find more about this pattern in the [Invalidation from Mutations](https://tanstack.com/query/latest/docs/framework/react/guides/invalidations-from-mutations) section of react-query.
:::

## Example

::: code-group

```tsx [src/app.tsx]
import { $api } from "./api";

export const App = () => {
const { mutate } = $api.useMutation("delete", "/users", {
onSuccess: () => {
const queryKey = $api.getKey("get", "/count-users");
queryClient.invalidateQueries({ queryKey });
},
});

return (
<button onClick={() => mutate({ body: { firstname: "John" } })}>
Delete John
</button>
);
};
```

```ts [src/api.ts]
import createFetchClient from "openapi-fetch";
import createClient from "openapi-react-query";
import type { paths } from "./my-openapi-3-schema"; // generated by openapi-typescript

const fetchClient = createFetchClient<paths>({
baseUrl: "https://myapi.dev/v1/",
});
export const $api = createClient(fetchClient);
```

:::

## Api

```tsx
const queryKey = $api.getKey(method, path, init);
```

**Arguments**

- `method` **(required)**
- The HTTP method to use for the request.
- The method is used as key. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information.
- `path` **(required)**
- The pathname to use for the request.
- Must be an available path for the given method in your schema.
- The pathname is used as key. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for more information.
- `init`
- The fetch options to use for the request.
14 changes: 14 additions & 0 deletions packages/openapi-react-query/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,20 @@ export type UseMutationMethod<Paths extends Record<string, Record<HttpMethod, {}
queryClient?: QueryClient,
) => UseMutationResult<Response["data"], Response["error"], Init>;

export type GetKeyMethod<
Paths extends Record<string, Record<HttpMethod, {}>> = Record<string, Record<HttpMethod, {}>>,
> = <
Method extends HttpMethod,
Path extends PathsWithMethod<Paths, Method>,
Init extends MaybeOptionalInit<Paths[Path], Method>,
>(
method: Method,
url: Path,
init?: Init,
) => [Method, Path, Init | undefined];

export interface OpenapiQueryClient<Paths extends {}, Media extends MediaType = MediaType> {
getKey: GetKeyMethod<Paths>;
useQuery: UseQueryMethod<Paths, Media>;
useSuspenseQuery: UseSuspenseQueryMethod<Paths, Media>;
useMutation: UseMutationMethod<Paths, Media>;
Expand All @@ -66,6 +79,7 @@ export default function createClient<Paths extends {}, Media extends MediaType =
client: FetchClient<Paths, Media>,
): OpenapiQueryClient<Paths, Media> {
return {
getKey: (method, path, init) => [method, path, init],
useQuery: (method, path, ...[init, options, queryClient]) => {
return useQuery(
{
Expand Down
55 changes: 55 additions & 0 deletions packages/openapi-react-query/test/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -451,4 +451,59 @@ describe("client", () => {
});
});
});

describe("getKey", () => {
it("should return correct key", () => {
const fetchClient = createFetchClient<paths>({ baseUrl });
const client = createClient(fetchClient);

const key = client.getKey("get", "/string-array", {});

expect(key).toEqual(["get", "/string-array", {}]);
});

it("should invalidate query", async () => {
const fetchClient = createFetchClient<paths>({ baseUrl });
const client = createClient(fetchClient);

useMockRequestHandler({
baseUrl,
method: "get",
path: "/string-array",
status: 200,
body: ["one", "two", "three"],
});

const { result } = renderHook(() => client.useQuery("get", "/string-array"), {
wrapper,
});

await waitFor(() => expect(result.current.isFetching).toBe(false));

const { data, error } = result.current;

expect(data).toBeDefined();
data && expect(data[0]).toBe("one");
expect(error).toBeNull();

const queryKey = client.getKey("get", "/string-array");

expect(
queryClient
.getQueryCache()
.getAll()
.map((p) => p.queryKey),
).toEqual([queryKey]);

// Remove query
await queryClient.removeQueries({ queryKey: queryKey });

expect(
queryClient
.getQueryCache()
.getAll()
.map((p) => p.queryKey),
).not.toEqual([queryKey]);
});
});
});