diff --git a/src/Get.test.tsx b/src/Get.test.tsx index f00fa852..b904bea7 100644 --- a/src/Get.test.tsx +++ b/src/Get.test.tsx @@ -155,6 +155,27 @@ describe("Get", () => { }); }); + it("should handle network error", async () => { + nock("https://my-awesome-api.fake") + .get("/") + .replyWithError({ message: "You shall not pass!" }); + + const children = jest.fn(); + children.mockReturnValue(
); + + render( + + {children} + , + ); + + await wait(() => expect(children.mock.calls.length).toBe(2)); + expect(children.mock.calls[1][0]).toEqual(null); + expect(children.mock.calls[1][1].error).toMatchObject({ + message: "Failed to fetch: request to https://my-awesome-api.fake failed, reason: You shall not pass!", + }); + }); + it("should deal with non standard server error response (nginx style)", async () => { nock("https://my-awesome-api.fake") .get("/") diff --git a/src/Get.tsx b/src/Get.tsx index ecf06f8b..5cad4540 100644 --- a/src/Get.tsx +++ b/src/Get.tsx @@ -249,36 +249,46 @@ class ContextlessGet extends React.Component< }; const request = new Request(makeRequestPath(), this.getRequestOptions(thisRequestOptions)); - const response = await fetch(request, { signal: this.signal }); - const { data, responseError } = await processResponse(response); + try { + const response = await fetch(request, { signal: this.signal }); + const { data, responseError } = await processResponse(response); - // avoid state updates when component has been unmounted - if (this.signal.aborted) { - return; - } + // avoid state updates when component has been unmounted + if (this.signal.aborted) { + return; + } - if (!response.ok || responseError) { - const error = { - message: `Failed to fetch: ${response.status} ${response.statusText}${responseError ? " - " + data : ""}`, - data, - }; + if (!response.ok || responseError) { + const error = { + message: `Failed to fetch: ${response.status} ${response.statusText}${responseError ? " - " + data : ""}`, + data, + }; - this.setState({ - loading: false, - error, - }); + this.setState({ + loading: false, + error, + }); - if (!this.props.localErrorOnly && this.props.onError) { - this.props.onError(error, () => this.fetch(requestPath, thisRequestOptions), response); - } + if (!this.props.localErrorOnly && this.props.onError) { + this.props.onError(error, () => this.fetch(requestPath, thisRequestOptions), response); + } - return null; - } + return null; + } - const resolved = await resolveData({ data, resolve }); + const resolved = await resolveData({ data, resolve }); - this.setState({ loading: false, data: resolved.data, error: resolved.error }); - return data; + this.setState({ loading: false, data: resolved.data, error: resolved.error }); + return data; + } catch (e) { + this.setState({ + loading: false, + error: { + message: `Failed to fetch: ${e.message}`, + data: e, + }, + }); + } }; public render() {