async-fetch 0.1.6 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,59 +10,58 @@ $ npm i async-fetch
10
10
 
11
11
  ## Usage
12
12
 
13
- Provide your config and handle the response.
13
+ Provide your request config and handle the response.
14
14
 
15
15
  ```javascript
16
16
  import React from "react";
17
17
  import useAsyncFetch from "async-fetch";
18
18
 
19
- const { pending, data, error, sendRequest, cancelRequest } = useAsyncFetch(
20
- "https://jsonplaceholder.typicode.com/todos/1"
21
- );
19
+ const App = () => {
20
+ const { pending, data, error, sendRequest, cancelRequest } = useAsyncFetch(
21
+ "http://localhost:5000/api/v1/"
22
+ );
22
23
 
23
- return pending ? (
24
- "Loading..."
25
- ) : data ? (
26
- "Data: " + JSON.stringify(data)
27
- ) : error ? (
28
- "Error: " + error.toString()
29
- ) : (
30
- <React.Fragment>
31
- <br />
32
- <br />
33
- <button onClick={sendRequest}>Send request.</button>
34
- <br />
35
- <br />
36
- <button onClick={cancelRequest}>Cancel request.</button>
37
- </React.Fragment>
38
- );
24
+ return (
25
+ <React.Fragment>
26
+ <button onClick={sendRequest}>Send request.</button>
27
+ <br />
28
+ <br />
29
+ <button onClick={cancelRequest} disabled={!pending}>
30
+ Cancel request.
31
+ </button>
32
+ <br />
33
+ <br />
34
+ {pending
35
+ ? "Loading..."
36
+ : data
37
+ ? JSON.stringify(data)
38
+ : error
39
+ ? "Error: " + error.toString()
40
+ : ""}
41
+ </React.Fragment>
42
+ );
43
+ };
44
+
45
+ export default App;
39
46
  ```
40
47
 
41
48
  ### Available IN Props And Definitions
42
49
 
43
- The minimum requirement for the hook is either a url string or an object with a url property.
44
-
45
- | Key | Type | Definition | Default |
46
- | --------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
47
- | initialPending | Boolean | Initial boolean of the pending state. | |
48
- | initialError | Any | Initial value of the error state. | |
49
- | initialData | Any | Initial value of the data state. | |
50
- | useEffectDependency | Array | Dependency array for the useEffect. | [] |
51
- | disableController | Boolean | To allow fetch's AbortController API to cancel requests. | |
52
- | poll | Number | Time interval (in milliseconds) for polling. | |
53
- | manual | Boolean | Condition where if true the request won't send unless called using the sendRequest OUT property. | |
54
- | condition | Boolean | Conditional statement where if false, the request won't send. | |
55
- | url | String | URL to send request to. | |
56
- | method | String | Request method type. | "GET" |
57
- | query | Object | Query parameters to include in the request. | |
58
- | data | Object | Data object to include in the request body. | |
59
- | initialResponseParser | String | Parser method to use on the initial response. | "json" |
60
- | onStart | Function | Callback function to run before the request is sent. | |
61
- | onSuccess | Function | Callback function to run after the response has been handled using the initialResponseParser. The parsed response is available in the callback. | |
62
- | onFail | Function | Callback function to run when the request responds with an error. The error is available in the callback. | |
63
- | onFinish | Function | Callback function to run when after the request is completed, regardless of success or failure | |
50
+ The minimum requirement for the hook is either a url string or an object with a url property. It is assumed that any other property that's provided is to be used for the actual fetch.
64
51
 
65
- It is assumed that any other property that's provided is to be used for the actual fetch.
52
+ | Key | Type | Definition | Default |
53
+ | --------- | -------- | -------------------------------------------------------------------------------------------------------------- | ------- |
54
+ | url | String | URL to send request to. | |
55
+ | query | Object | Query parameters to include in the request (alt key name: "params"). | |
56
+ | data | Object | Data object to include in the request body. | |
57
+ | parser | String | Method used to parse the response. | "json" |
58
+ | onStart | Function | Callback function to run before the request is sent. | |
59
+ | onSuccess | Function | Callback function to run after the response has been parsed. The parsed response is available in the callback. | |
60
+ | onFail | Function | Callback function to run when the request responds with an error. The error is available in the callback. | |
61
+ | onFinish | Function | Callback function to run after the request has completed, regardless of success or failure. | |
62
+ | deps | Array | Dependency array for the useEffect. | [] |
63
+ | ignore | Boolean | Condition where if true the request won't send unless called using the sendRequest OUT property. | |
64
+ | poll | Number | Time interval (in milliseconds) for polling. | |
66
65
 
67
66
  ### Available OUT Props And Definitions
68
67
 
@@ -71,8 +70,5 @@ It is assumed that any other property that's provided is to be used for the actu
71
70
  | pending | Boolean | Whether the request is active or not. |
72
71
  | error | Any | The response error. |
73
72
  | data | Any | The response data. |
74
- | setPending | Boolean | Custom setter for pending state. |
75
- | setError | Any | Custom setter for error state. |
76
- | setData | Any | Custom setter for data state. |
77
73
  | sendRequest | Function | Function to send the request manually. |
78
74
  | cancelRequest | Function | Function to cancel the request manually. |
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "async-fetch",
3
- "version": "0.1.6",
4
- "description": "Asynchronously use fetch for requests within React components.",
3
+ "version": "0.1.9",
4
+ "description": "Use fetch asynchronously for requests within React components.",
5
5
  "main": "useAsyncFetch.js",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1"
package/useAsyncFetch.js CHANGED
@@ -1,128 +1,120 @@
1
- const { useState, useEffect } = require("react");
2
- const useInterval = require("./useInterval");
1
+ import { useState, useEffect } from "react";
2
+ import useInterval from "./useInterval";
3
3
 
4
4
  let controller;
5
5
 
6
- function useAsyncFetch(props, fetchProps) {
6
+ function useAsyncFetch(props, props2) {
7
7
  let {
8
- initialPending,
9
- initialError,
10
- initialData,
11
- useEffectDependency = [],
12
- disableController,
13
- poll = null,
14
- manual,
15
- condition,
16
- method = "GET",
8
+ url,
17
9
  query,
18
- data: bodyData,
19
- initialResponseParser = "json",
10
+ params,
11
+ data: requestData,
12
+ parser = "json",
20
13
  onStart,
21
14
  onSuccess,
22
15
  onFail,
23
16
  onFinish,
24
- ...fetchOptions
25
- } = props && props.constructor === Object ? props : {};
17
+ deps = [],
18
+ ignore,
19
+ poll,
20
+ ...props3
21
+ } = props instanceof Object ? props : {};
26
22
 
27
- const url =
28
- props &&
29
- ((props.constructor === Object && props.url) ||
30
- (props.constructor === String && props));
23
+ if (typeof props === "string") url = props;
31
24
 
32
- const [pending, setPending] = useState(initialPending);
33
- const [error, setError] = useState(initialError);
34
- const [data, setData] = useState(initialData);
35
- const [unmounted, setUnmounted] = useState();
25
+ const [pending1, setPending1] = useState();
36
26
 
37
- function cancelActiveRequest() {
38
- if (controller && controller.abort) controller.abort();
39
- }
27
+ const [pending2, setPending2] = useState();
40
28
 
41
- function sendRequest(props = {}) {
42
- if (url && condition !== false && !unmounted) {
43
- if (disableController !== true) cancelActiveRequest();
29
+ const [error, setError] = useState();
44
30
 
45
- if (!props.excludePendingUpdate) setPending(true);
31
+ const [data, setData] = useState();
46
32
 
47
- setError();
33
+ const [unmounted, setUnmounted] = useState();
48
34
 
49
- if (onStart) onStart();
35
+ const cancelActiveRequest = () => controller?.abort?.();
50
36
 
51
- query = query ? "?" + new URLSearchParams(query).toString() : "";
37
+ async function sendRequest() {
38
+ try {
39
+ cancelActiveRequest();
52
40
 
53
41
  controller = new AbortController();
54
42
 
55
- const options = {
56
- method,
57
- signal: controller && controller.signal,
58
- ...fetchOptions,
59
- body:
60
- (bodyData || fetchOptions.body) &&
61
- JSON.stringify({ ...bodyData, ...fetchOptions.body }),
62
- ...fetchProps,
63
- };
64
-
65
- fetch(url + query, options)
66
- .then((initialResponse) => {
67
- if (!unmounted) {
68
- if (!initialResponse.ok) {
69
- const throwError =
70
- initialResponse.statusText || initialResponse.status.toString();
71
- throw Error(throwError);
72
- }
73
- return initialResponse[initialResponseParser]();
74
- }
75
- })
76
- .then((parsedResponse) => {
77
- if (!unmounted) {
78
- setData(parsedResponse);
79
- if (onSuccess) onSuccess(parsedResponse);
80
- }
81
- })
82
- .catch((responseError) => {
83
- if (!unmounted) {
84
- setError(responseError);
85
- if (onFail) onFail(responseError);
86
- }
87
- })
88
- .finally(() => {
89
- if (!unmounted) {
90
- setPending();
91
- if (onFinish) onFinish();
92
- }
93
- });
43
+ if (!unmounted) {
44
+ if (pending1) {
45
+ setPending2(true);
46
+ } else setPending1(true);
47
+ setError();
48
+ if (onStart) onStart();
49
+ }
50
+
51
+ if (query || params)
52
+ url += "?" + new URLSearchParams(query || params).toString();
53
+
54
+ const response = await fetch(url, {
55
+ signal: controller?.signal,
56
+ body: requestData && JSON.stringify(requestData),
57
+ ...props2,
58
+ ...props3,
59
+ });
60
+
61
+ if (!response.ok)
62
+ throw new Error(
63
+ JSON.stringify({
64
+ code: r.status,
65
+ text: r.statusText,
66
+ response: await response.text(),
67
+ })
68
+ );
69
+
70
+ const parsedResponse = await response[parser]();
71
+
72
+ if (!unmounted) {
73
+ setData(parsedResponse);
74
+ if (onSuccess) onSuccess(parsedResponse);
75
+ }
76
+ } catch (error) {
77
+ if (!unmounted && error.name !== "AbortError") {
78
+ let errorJson;
79
+ try {
80
+ errorJson = error.toString().replace("Error:", "");
81
+ errorJson = JSON.parse(errorJson.trim());
82
+ } catch {}
83
+ setError(errorJson || error);
84
+ if (onFail) onFail(errorJson || error);
85
+ }
86
+ } finally {
87
+ if (!unmounted) {
88
+ if (pending1) {
89
+ setPending2(false);
90
+ } else setPending1(false);
91
+ if (onFinish) onFinish();
92
+ }
94
93
  }
95
94
  }
96
95
 
97
96
  useEffect(() => {
98
- if (!url) console.warn("[async-fetch] url is required.");
99
- if (!manual) sendRequest();
100
- // eslint-disable-next-line
101
- }, useEffectDependency);
97
+ if (ignore !== true) sendRequest();
98
+ }, deps); // eslint-disable-line
102
99
 
103
100
  useInterval(() => {
104
- sendRequest({ excludePendingUpdate: true });
101
+ sendRequest();
105
102
  }, poll);
106
103
 
107
- useEffect(
108
- () => () => {
104
+ useEffect(() => {
105
+ return () => {
109
106
  setUnmounted(true);
110
- if (disableController !== true) cancelActiveRequest();
111
- },
112
- // eslint-disable-next-line
113
- []
114
- );
107
+ cancelActiveRequest();
108
+ };
109
+ }, []);
115
110
 
116
111
  return {
117
- pending,
112
+ pending: pending1 || pending2,
118
113
  error,
119
114
  data,
120
- setPending,
121
- setError,
122
- setData,
123
- cancelRequest: cancelActiveRequest,
124
115
  sendRequest,
116
+ cancelRequest: cancelActiveRequest,
125
117
  };
126
118
  }
127
119
 
128
- module.exports = useAsyncFetch;
120
+ export default useAsyncFetch;
package/useInterval.js CHANGED
@@ -1,22 +1,22 @@
1
- // https://github.com/Hermanya/use-interval/blob/master/src/index.tsx
2
-
3
- const { useEffect, useRef } = require("react");
4
-
5
- const noop = () => {};
1
+ import { useEffect, useRef } from "react";
6
2
 
7
3
  function useInterval(callback, poll) {
8
- const savedCallback = useRef(noop);
4
+ const callbackRef = useRef(() => {}); // noop
9
5
 
10
6
  useEffect(() => {
11
- savedCallback.current = callback;
7
+ callbackRef.current = callback;
12
8
  });
13
9
 
14
10
  useEffect(() => {
15
- if (poll === null || poll === false) return;
16
- const tick = () => savedCallback.current();
17
- const id = setInterval(tick, poll);
18
- return () => clearInterval(id);
11
+ if (!poll) return;
12
+ const onTick = () => callbackRef.current();
13
+ const interval = setInterval(onTick, poll);
14
+ return () => {
15
+ clearInterval(interval);
16
+ };
19
17
  }, [poll]);
20
18
  }
21
19
 
22
- module.exports = useInterval;
20
+ export default useInterval;
21
+
22
+ // https://github.com/Hermanya/use-interval/blob/master/src/index.tsx