diff --git a/.changeset/signal.md b/.changeset/signal.md new file mode 100644 index 000000000..f1e82eb25 --- /dev/null +++ b/.changeset/signal.md @@ -0,0 +1,5 @@ +--- +"openapi-react-query": patch +--- + +Pass down signal to fetch function this way `useQuery` and `useSuspenseQuery` can cancel queries. diff --git a/packages/openapi-react-query/src/index.ts b/packages/openapi-react-query/src/index.ts index 438c7aa94..95dde2d9d 100644 --- a/packages/openapi-react-query/src/index.ts +++ b/packages/openapi-react-query/src/index.ts @@ -70,10 +70,10 @@ export default function createClient { + queryFn: async ({ signal }) => { const mth = method.toUpperCase() as keyof typeof client; const fn = client[mth] as ClientMethod; - const { data, error } = await fn(path, init as any); // TODO: find a way to avoid as any + const { data, error } = await fn(path, { signal, ...(init as any) }); // TODO: find a way to avoid as any if (error || !data) { throw error; } @@ -88,10 +88,10 @@ export default function createClient { + queryFn: async ({ signal }) => { const mth = method.toUpperCase() as keyof typeof client; const fn = client[mth] as ClientMethod; - const { data, error } = await fn(path, init as any); // TODO: find a way to avoid as any + const { data, error } = await fn(path, { signal, ...(init as any) }); // TODO: find a way to avoid as any if (error || !data) { throw error; } diff --git a/packages/openapi-react-query/test/index.test.tsx b/packages/openapi-react-query/test/index.test.tsx index 64a9a81e1..0acbce4ad 100644 --- a/packages/openapi-react-query/test/index.test.tsx +++ b/packages/openapi-react-query/test/index.test.tsx @@ -3,7 +3,7 @@ import { server, baseUrl, useMockRequestHandler } from "./fixtures/mock-server.j import type { paths } from "./fixtures/api.js"; import createClient from "../src/index.js"; import createFetchClient from "openapi-fetch"; -import { fireEvent, render, renderHook, screen, waitFor } from "@testing-library/react"; +import { fireEvent, render, renderHook, screen, waitFor, act } from "@testing-library/react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { Suspense, type ReactNode } from "react"; import { ErrorBoundary } from "react-error-boundary"; @@ -109,6 +109,26 @@ describe("client", () => { expectTypeOf(error).toEqualTypeOf<{ code: number; message: string } | null>(); }); + it("passes abort signal to fetch", async () => { + let signalPassedToFetch: AbortSignal | undefined; + + const fetchClient = createFetchClient({ + baseUrl, + fetch: async ({ signal }) => { + signalPassedToFetch = signal; + await new Promise(() => {}); + return Response.error(); + }, + }); + const client = createClient(fetchClient); + + const { unmount } = renderHook(() => client.useQuery("get", "/string-array"), { wrapper }); + + unmount(); + + expect(signalPassedToFetch?.aborted).toBeTruthy(); + }); + describe("params", () => { it("should be required if OpenAPI schema requires params", async () => { const fetchClient = createFetchClient({ baseUrl }); @@ -258,6 +278,29 @@ describe("client", () => { await waitFor(() => rendered.findByText("data: Hello")); }); + + it("passes abort signal to fetch", async () => { + let signalPassedToFetch: AbortSignal | undefined; + + const fetchClient = createFetchClient({ + baseUrl, + fetch: async ({ signal }) => { + signalPassedToFetch = signal; + await new Promise(() => {}); + return Response.error(); + }, + }); + const client = createClient(fetchClient); + const queryClient = new QueryClient({}); + + const { unmount } = renderHook(() => client.useSuspenseQuery("get", "/string-array", {}, {}, queryClient)); + + unmount(); + + await act(() => queryClient.cancelQueries()); + + expect(signalPassedToFetch?.aborted).toBeTruthy(); + }); }); describe("useMutation", () => {