diff --git a/.changeset/fix-query-route-response.md b/.changeset/fix-query-route-response.md new file mode 100644 index 0000000000..55d77cf45e --- /dev/null +++ b/.changeset/fix-query-route-response.md @@ -0,0 +1,5 @@ +--- +"@remix-run/router": patch +--- + +Fix an issue in `queryRoute` that was not always identifying thrown `Response` instances diff --git a/contributors.yml b/contributors.yml index b0fc66fe83..3f31fe2a05 100644 --- a/contributors.yml +++ b/contributors.yml @@ -48,6 +48,7 @@ - cvbuelow - damianstasik - danielberndt +- daniilguit - dauletbaev - david-crespo - decadentsavant diff --git a/packages/router/__tests__/router-test.ts b/packages/router/__tests__/router-test.ts index 51fe38a0ff..4bdd1c4c7f 100644 --- a/packages/router/__tests__/router-test.ts +++ b/packages/router/__tests__/router-test.ts @@ -16230,6 +16230,46 @@ describe("a router", () => { expect(await data.json()).toEqual({ key: "value" }); }); + it("should not unwrap responses thrown from loaders", async () => { + let response = json({ key: "value" }); + let { queryRoute } = createStaticHandler([ + { + id: "root", + path: "/", + loader: () => Promise.reject(response), + }, + ]); + let request = createRequest("/"); + let data; + try { + await queryRoute(request, { routeId: "root" }); + } catch (e) { + data = e; + } + expect(data instanceof Response).toBe(true); + expect(await data.json()).toEqual({ key: "value" }); + }); + + it("should not unwrap responses thrown from actions", async () => { + let response = json({ key: "value" }); + let { queryRoute } = createStaticHandler([ + { + id: "root", + path: "/", + action: () => Promise.reject(response), + }, + ]); + let request = createSubmitRequest("/"); + let data; + try { + await queryRoute(request, { routeId: "root" }); + } catch (e) { + data = e; + } + expect(data instanceof Response).toBe(true); + expect(await data.json()).toEqual({ key: "value" }); + }); + it("should handle aborted load requests", async () => { let dfd = createDeferred(); let controller = new AbortController(); diff --git a/packages/router/router.ts b/packages/router/router.ts index ca7163d13b..9d28f016df 100644 --- a/packages/router/router.ts +++ b/packages/router/router.ts @@ -2789,7 +2789,7 @@ export function createStaticHandler( // it to bail out and then return or throw here based on whether the user // returned or threw if (isQueryRouteResponse(e)) { - if (e.type === ResultType.error && !isRedirectResponse(e.response)) { + if (e.type === ResultType.error) { throw e.response; } return e.response; @@ -3741,11 +3741,12 @@ async function callLoaderOrAction( // without unwrapping. We do this with the QueryRouteResponse wrapper // interface so we can know whether it was returned or thrown if (opts.isRouteRequest) { - // eslint-disable-next-line no-throw-literal - throw { - type: resultType || ResultType.data, + let queryRouteResponse: QueryRouteResponse = { + type: + resultType === ResultType.error ? ResultType.error : ResultType.data, response: result, }; + throw queryRouteResponse; } let data: any; @@ -4220,7 +4221,7 @@ function isQueryRouteResponse(obj: any): obj is QueryRouteResponse { return ( obj && isResponse(obj.response) && - (obj.type === ResultType.data || ResultType.error) + (obj.type === ResultType.data || obj.type === ResultType.error) ); }