,
218 | loadMore?: () => mixed,
219 | hasMore: boolean
220 | };
221 | ```
222 |
223 | ## Who Uses react-fetch-hook
224 |
225 | ### Open Source projects
226 |
227 | * [react-figma](https://github.com/react-figma/react-figma)
228 | * [awesome-web-animation](https://github.com/sergey-pimenov/awesome-web-animation)
229 | * [redux-helpers](https://github.com/lecstor/redux-helpers)
230 | * [flowmap.blue](https://github.com/FlowmapBlue/flowmap.blue)
231 |
232 | ### Companies
233 |
234 | * [Redis Agency](https://redis.agency/)
235 | * [Lessmess Agency](https://lessmess.agency)
236 | * [BigDatr](https://bigdatr.com/)
237 | * [Fabrique numérique des Ministères Sociaux](https://incubateur.social.gouv.fr/)
238 |
239 | [See more](https://github.com/ilyalesik/react-fetch-hook/network/dependents)
240 |
--------------------------------------------------------------------------------
/test/useFetch.test.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { render, wait } from "react-testing-library";
3 | import useFetch from "../index";
4 |
5 | describe("useFetch", () => {
6 | beforeEach(() => {
7 | fetch.resetMocks();
8 | });
9 |
10 | it("call with only url", async () => {
11 | fetch.mockResponse(JSON.stringify({ data: "12345" }));
12 |
13 | const Component = () => {
14 | const result = useFetch("https://google.com");
15 | return {result.data && result.data.data}
;
16 | };
17 |
18 | const { container, rerender } = render();
19 |
20 | await wait(() => {
21 | rerender();
22 |
23 | expect(fetch.mock.calls.length).toEqual(1);
24 | expect(container).toHaveTextContent("12345");
25 | expect(fetch.mock.calls[0][0]).toEqual("https://google.com");
26 | });
27 | });
28 |
29 | it("isLoading by default", async () => {
30 | fetch.mockResponse(JSON.stringify({ data: "12345" }));
31 |
32 | const Component = () => {
33 | const result = useFetch("https://google.com");
34 | return {result.isLoading && "test"}
;
35 | };
36 |
37 | const { container, rerender } = render();
38 | expect(container).toHaveTextContent("test");
39 | });
40 |
41 | it("call with url and options", async () => {
42 | fetch.mockResponse(JSON.stringify({ data: "12345" }));
43 | const options = {
44 | headers: {
45 | Accept: "application/json, application/xml, text/plain, text/html, *.*",
46 | "Content-Type": "application/json; charset=utf-8"
47 | }
48 | };
49 |
50 | const Component = () => {
51 | const result = useFetch("https://google.com", { ...options });
52 | return {result.isLoading}
;
53 | };
54 |
55 | const { rerender } = render();
56 |
57 | await wait(() => {
58 | rerender();
59 |
60 | expect(fetch.mock.calls.length).toEqual(1);
61 | expect(fetch.mock.calls[0][0]).toEqual("https://google.com");
62 | expect(fetch.mock.calls[0][1]).toMatchObject({ ...options });
63 | });
64 | });
65 |
66 | it("call with url, options with formatter", async () => {
67 | fetch.mockResponse(JSON.stringify({ data: "12345" }));
68 | const options = {
69 | headers: {
70 | Accept: "application/json, application/xml, text/plain, text/html, *.*",
71 | "Content-Type": "application/json; charset=utf-8"
72 | }
73 | };
74 | const formatterMock = jest.fn();
75 | formatterMock.mockReturnValueOnce("xxx");
76 |
77 | const Component = () => {
78 | const result = useFetch("https://google.com", { ...options, formatter: formatterMock });
79 | return {result.data}
;
80 | };
81 |
82 | const { container, rerender } = render();
83 |
84 | await wait(() => {
85 | rerender();
86 |
87 | expect(fetch.mock.calls.length).toEqual(1);
88 | expect(formatterMock.mock.calls.length).toEqual(1);
89 | expect(container).toHaveTextContent("xxx");
90 | expect(fetch.mock.calls[0][0]).toEqual("https://google.com");
91 | expect(fetch.mock.calls[0][1]).toMatchObject({ ...options });
92 | });
93 | });
94 |
95 | it("call with url, options, special options with formatter", async () => {
96 | fetch.mockResponse(JSON.stringify({ data: "12345" }));
97 | const options = {
98 | headers: {
99 | Accept: "application/json, application/xml, text/plain, text/html, *.*",
100 | "Content-Type": "application/json; charset=utf-8"
101 | }
102 | };
103 | const formatterMock = jest.fn();
104 | formatterMock.mockReturnValueOnce("xxx");
105 |
106 | const Component = () => {
107 | const result = useFetch("https://google.com", { ...options }, { formatter: formatterMock});
108 | return {result.data}
;
109 | };
110 |
111 | const { container, rerender } = render();
112 |
113 | await wait(() => {
114 | rerender();
115 |
116 | expect(fetch.mock.calls.length).toEqual(1);
117 | expect(formatterMock.mock.calls.length).toEqual(1);
118 | expect(container).toHaveTextContent("xxx");
119 | expect(fetch.mock.calls[0][0]).toEqual("https://google.com");
120 | expect(fetch.mock.calls[0][1]).toMatchObject({ ...options });
121 | });
122 | });
123 |
124 | it("call with url, options with preventCallFetch: false and depends", async () => {
125 | fetch.mockResponse(JSON.stringify({ data: "12345" }));
126 | const options = {
127 | headers: {
128 | Accept: "application/json, application/xml, text/plain, text/html, *.*",
129 | "Content-Type": "application/json; charset=utf-8"
130 | }
131 | };
132 |
133 | const Component = () => {
134 | const result = useFetch("https://google.com", { ...options, depends: ["xxx"], preventCallFetch: false });
135 | return {result.data && result.data.data}
;
136 | };
137 |
138 | const { container, rerender } = render();
139 |
140 | await wait(() => {
141 | rerender();
142 |
143 | expect(fetch.mock.calls.length).toEqual(1);
144 | });
145 | });
146 |
147 | it("call with url, options with depends", async () => {
148 | fetch.mockResponse(JSON.stringify({ data: "12345" }));
149 | const options = {
150 | headers: {
151 | Accept: "application/json, application/xml, text/plain, text/html, *.*",
152 | "Content-Type": "application/json; charset=utf-8"
153 | }
154 | };
155 |
156 | const Component = () => {
157 | const result = useFetch("https://google.com", { ...options, depends: [true, false] });
158 | return {result.data && result.data.data}
;
159 | };
160 |
161 | const { container, rerender } = render();
162 |
163 | await wait(() => {
164 | rerender();
165 |
166 | expect(fetch.mock.calls.length).toEqual(0);
167 | });
168 | });
169 |
170 | it("call with url, options with depends never set isLoading", async () => {
171 | const isLoadingWatcher = jest.fn();
172 | fetch.mockResponse(JSON.stringify({ data: "12345" }));
173 | const options = {
174 | headers: {
175 | Accept: "application/json, application/xml, text/plain, text/html, *.*",
176 | "Content-Type": "application/json; charset=utf-8"
177 | }
178 | };
179 |
180 | const Component = () => {
181 | const result = useFetch("https://google.com", { ...options, depends: [false] });
182 | const isLoading = result.isLoading;
183 | React.useEffect(() => {
184 | if (isLoading) {
185 | isLoadingWatcher();
186 | }
187 | }, [isLoading])
188 | return {result.data && result.data.data}
;
189 | };
190 |
191 | const { container, rerender } = render();
192 |
193 | await wait(() => {
194 | rerender();
195 |
196 | expect(isLoadingWatcher.mock.calls.length).toEqual(0);
197 | });
198 | });
199 |
200 | it("call with url, options with depends at next arg", async () => {
201 | fetch.mockResponse(JSON.stringify({ data: "12345" }));
202 | const options = {
203 | headers: {
204 | Accept: "application/json, application/xml, text/plain, text/html, *.*",
205 | "Content-Type": "application/json; charset=utf-8"
206 | }
207 | };
208 |
209 | const fetchParams = ["https://google.com", options];
210 |
211 | const Component = () => {
212 | const result = useFetch(...fetchParams, { depends: [true, false] });
213 | return {result.data && result.data.data}
;
214 | };
215 |
216 | const { container, rerender } = render();
217 |
218 | await wait(() => {
219 | rerender();
220 |
221 | expect(fetch.mock.calls.length).toEqual(0);
222 | });
223 | });
224 |
225 | it("call with url, options with depends: [true] at next arg", async () => {
226 | fetch.mockResponse(JSON.stringify({ data: "12345" }));
227 | const options = {
228 | headers: {
229 | Accept: "application/json, application/xml, text/plain, text/html, *.*",
230 | "Content-Type": "application/json; charset=utf-8"
231 | }
232 | };
233 |
234 | const fetchParams = ["https://google.com", options];
235 |
236 | const Component = () => {
237 | const result = useFetch(...fetchParams, { depends: [true] });
238 | return {result.data && result.data.data}
;
239 | };
240 |
241 | const { container, rerender } = render();
242 |
243 | await wait(() => {
244 | rerender();
245 |
246 | expect(fetch.mock.calls.length).toEqual(1);
247 | });
248 | });
249 |
250 | it("call with url, options with depends with empty string", async () => {
251 | fetch.mockResponse(JSON.stringify({ data: "12345" }));
252 | const options = {
253 | headers: {
254 | Accept: "application/json, application/xml, text/plain, text/html, *.*",
255 | "Content-Type": "application/json; charset=utf-8"
256 | }
257 | };
258 |
259 | const Component = () => {
260 | const result = useFetch("https://google.com", { ...options, depends: [""] });
261 | return {result.data && result.data.data}
;
262 | };
263 |
264 | const { container, rerender } = render();
265 |
266 | await wait(() => {
267 | rerender();
268 |
269 | expect(fetch.mock.calls.length).toEqual(0);
270 | });
271 | });
272 |
273 | it("call with url, options with empty depends", async () => {
274 | fetch.mockResponse(JSON.stringify({ data: "12345" }));
275 | const options = {
276 | headers: {
277 | Accept: "application/json, application/xml, text/plain, text/html, *.*",
278 | "Content-Type": "application/json; charset=utf-8"
279 | }
280 | };
281 |
282 | const Component = () => {
283 | const result = useFetch("https://google.com", { ...options, depends: [] });
284 | return {result.data && result.data.data}
;
285 | };
286 |
287 | const { container, rerender } = render();
288 |
289 | await wait(() => {
290 | rerender();
291 |
292 | expect(fetch.mock.calls.length).toEqual(1);
293 | });
294 | });
295 |
296 | it("call with url, options with all true depends", async () => {
297 | fetch.mockResponse(JSON.stringify({ data: "12345" }));
298 | const options = {
299 | headers: {
300 | Accept: "application/json, application/xml, text/plain, text/html, *.*",
301 | "Content-Type": "application/json; charset=utf-8"
302 | }
303 | };
304 |
305 | const Component = () => {
306 | const result = useFetch("https://google.com", { ...options, depends: [true, true] });
307 | return {result.data && result.data.data}
;
308 | };
309 |
310 | const { container, rerender } = render();
311 |
312 | await wait(() => {
313 | rerender();
314 |
315 | expect(fetch.mock.calls.length).toEqual(1);
316 | });
317 | });
318 |
319 | it("error on throw error", async () => {
320 | fetch.mockReject(new Error("fake error message"));
321 |
322 | const Component = () => {
323 | const result = useFetch("https://google.com");
324 | return (result.error && result.error.message) || "text";
325 | };
326 |
327 | const { container, rerender } = render();
328 |
329 | await wait(() => {
330 | rerender();
331 |
332 | expect(fetch.mock.calls.length).toEqual(1);
333 | expect(container).toHaveTextContent("fake error message");
334 | expect(fetch.mock.calls[0][0]).toEqual("https://google.com");
335 | });
336 | });
337 |
338 | it("call with URL", async () => {
339 | fetch.mockResponse(JSON.stringify({ data: "12345" }));
340 |
341 | const url = new URL("https://google.com");
342 |
343 | url.search = new URLSearchParams({a: 1, b: 2}).toString();
344 |
345 | const Component = () => {
346 | const result = useFetch(url, {
347 | depends: ["1", 1]
348 | });
349 | return {result.data && result.data.data}
;
350 | };
351 |
352 | const { container, rerender } = render();
353 |
354 | await wait(() => {
355 | rerender();
356 | });
357 |
358 | await wait(() => {
359 | rerender();
360 |
361 | expect(fetch.mock.calls.length).toEqual(1);
362 | expect(container).toHaveTextContent("12345");
363 | expect(fetch.mock.calls[0][0]).toMatchObject(url);
364 | });
365 | });
366 | });
367 |
--------------------------------------------------------------------------------