async-fetch 0.1.5 → 0.1.8
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 +25 -32
- package/package.json +1 -1
- package/useAsyncFetch.js +71 -91
- package/useInterval.js +9 -9
package/README.md
CHANGED
|
@@ -10,10 +10,10 @@ $ 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
|
-
import
|
|
16
|
+
import React from "react";
|
|
17
17
|
import useAsyncFetch from "async-fetch";
|
|
18
18
|
|
|
19
19
|
const { pending, data, error, sendRequest, cancelRequest } = useAsyncFetch(
|
|
@@ -21,18 +21,20 @@ const { pending, data, error, sendRequest, cancelRequest } = useAsyncFetch(
|
|
|
21
21
|
);
|
|
22
22
|
|
|
23
23
|
return pending ? (
|
|
24
|
-
|
|
25
|
-
<p>Loading...</p>
|
|
26
|
-
<button onClick={cancelRequest}>Click here to cancel the request.</button>
|
|
27
|
-
</Fragment>
|
|
24
|
+
"Loading..."
|
|
28
25
|
) : data ? (
|
|
29
26
|
"Data: " + JSON.stringify(data)
|
|
30
27
|
) : error ? (
|
|
31
|
-
|
|
32
|
-
Error: {error.toString()}. Click here to try again.
|
|
33
|
-
</button>
|
|
28
|
+
"Error: " + error.toString()
|
|
34
29
|
) : (
|
|
35
|
-
<
|
|
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>
|
|
36
38
|
);
|
|
37
39
|
```
|
|
38
40
|
|
|
@@ -40,25 +42,19 @@ return pending ? (
|
|
|
40
42
|
|
|
41
43
|
The minimum requirement for the hook is either a url string or an object with a url property.
|
|
42
44
|
|
|
43
|
-
| Key
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
| data | Object | Data object to include in the request body. | |
|
|
57
|
-
| initialResponseParser | String | Parser method to use on the initial 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 handled using the initialResponseParser. 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 when after the request is completed, regardless of success or failure | |
|
|
45
|
+
| Key | Type | Definition | Default |
|
|
46
|
+
| -------------- | -------- | -------------------------------------------------------------------------------------------------------------- | ------- |
|
|
47
|
+
| url | String | URL to send request to. | |
|
|
48
|
+
| query | Object | Query parameters to include in the request (alt key name: "params"). | |
|
|
49
|
+
| data | Object | Data object to include in the request body. | |
|
|
50
|
+
| responseParser | String | Parser method to use on the response. | "json" |
|
|
51
|
+
| onStart | Function | Callback function to run before the request is sent. | |
|
|
52
|
+
| onSuccess | Function | Callback function to run after the response has been parsed. The parsed response is available in the callback. | |
|
|
53
|
+
| onFail | Function | Callback function to run when the request responds with an error. The error is available in the callback. | |
|
|
54
|
+
| onFinish | Function | Callback function to run after the request has completed, regardless of success or failure. | |
|
|
55
|
+
| useEffect | Array | Dependency array for the useEffect. | [] |
|
|
56
|
+
| ignoreEffect | Boolean | Condition where if true the request won't send unless called using the sendRequest OUT property. | |
|
|
57
|
+
| poll | Number | Time interval (in milliseconds) for polling. | |
|
|
62
58
|
|
|
63
59
|
It is assumed that any other property that's provided is to be used for the actual fetch.
|
|
64
60
|
|
|
@@ -69,8 +65,5 @@ It is assumed that any other property that's provided is to be used for the actu
|
|
|
69
65
|
| pending | Boolean | Whether the request is active or not. |
|
|
70
66
|
| error | Any | The response error. |
|
|
71
67
|
| data | Any | The response data. |
|
|
72
|
-
| setPending | Boolean | Custom setter for pending state. |
|
|
73
|
-
| setError | Any | Custom setter for error state. |
|
|
74
|
-
| setData | Any | Custom setter for data state. |
|
|
75
68
|
| sendRequest | Function | Function to send the request manually. |
|
|
76
69
|
| cancelRequest | Function | Function to cancel the request manually. |
|
package/package.json
CHANGED
package/useAsyncFetch.js
CHANGED
|
@@ -1,128 +1,108 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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, fetchProps = {}) {
|
|
7
7
|
let {
|
|
8
|
-
|
|
9
|
-
initialError,
|
|
10
|
-
initialData,
|
|
11
|
-
useEffectDependency = [],
|
|
12
|
-
disableController,
|
|
13
|
-
poll = null,
|
|
14
|
-
manual,
|
|
15
|
-
condition,
|
|
16
|
-
method = "GET",
|
|
8
|
+
url,
|
|
17
9
|
query,
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
params,
|
|
11
|
+
data: requestData,
|
|
12
|
+
responseParser = "json",
|
|
20
13
|
onStart,
|
|
21
14
|
onSuccess,
|
|
22
15
|
onFail,
|
|
23
16
|
onFinish,
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
ignoreEffect,
|
|
18
|
+
useEffect: useEffectDependencies = [],
|
|
19
|
+
poll,
|
|
20
|
+
...fetchProps2
|
|
21
|
+
} = props instanceof Object ? props : {};
|
|
26
22
|
|
|
27
|
-
|
|
28
|
-
props &&
|
|
29
|
-
((props.constructor === Object && props.url) ||
|
|
30
|
-
(props.constructor === String && props));
|
|
23
|
+
if (typeof props === "string") url = props;
|
|
31
24
|
|
|
32
|
-
const [
|
|
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
|
-
|
|
38
|
-
if (controller && controller.abort) controller.abort();
|
|
39
|
-
}
|
|
27
|
+
const [pending2, setPending2] = useState();
|
|
40
28
|
|
|
41
|
-
|
|
42
|
-
if (url && condition !== false && !unmounted) {
|
|
43
|
-
if (disableController !== true) cancelActiveRequest();
|
|
29
|
+
const [error, setError] = useState();
|
|
44
30
|
|
|
45
|
-
|
|
31
|
+
const [data, setData] = useState();
|
|
46
32
|
|
|
47
|
-
|
|
33
|
+
const [unmounted, setUnmounted] = useState();
|
|
48
34
|
|
|
49
|
-
|
|
35
|
+
const cancelActiveRequest = () => controller?.abort?.();
|
|
50
36
|
|
|
51
|
-
|
|
37
|
+
async function sendRequest() {
|
|
38
|
+
try {
|
|
39
|
+
cancelActiveRequest();
|
|
52
40
|
|
|
53
41
|
controller = new AbortController();
|
|
54
42
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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),
|
|
62
57
|
...fetchProps,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
})
|
|
88
|
-
.finally(() => {
|
|
89
|
-
if (!unmounted) {
|
|
90
|
-
setPending();
|
|
91
|
-
if (onFinish) onFinish();
|
|
92
|
-
}
|
|
93
|
-
});
|
|
58
|
+
...fetchProps2,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (!response.ok)
|
|
62
|
+
throw new Error(response.statusText || response.status.toString());
|
|
63
|
+
|
|
64
|
+
const parsedResponse = await response[responseParser]();
|
|
65
|
+
|
|
66
|
+
if (!unmounted) {
|
|
67
|
+
setData(parsedResponse);
|
|
68
|
+
if (onSuccess) onSuccess(parsedResponse);
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
if (!unmounted && error.name !== "AbortError") {
|
|
72
|
+
setError(error);
|
|
73
|
+
if (onFail) onFail(error);
|
|
74
|
+
}
|
|
75
|
+
} finally {
|
|
76
|
+
if (!unmounted) {
|
|
77
|
+
if (pending1) {
|
|
78
|
+
setPending2(false);
|
|
79
|
+
} else setPending1(false);
|
|
80
|
+
if (onFinish) onFinish();
|
|
81
|
+
}
|
|
94
82
|
}
|
|
95
83
|
}
|
|
96
|
-
|
|
97
84
|
useEffect(() => {
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
// eslint-disable-next-line
|
|
101
|
-
}, useEffectDependency);
|
|
85
|
+
if (ignoreEffect !== true) sendRequest();
|
|
86
|
+
}, useEffectDependencies); // eslint-disable-line
|
|
102
87
|
|
|
103
88
|
useInterval(() => {
|
|
104
|
-
sendRequest(
|
|
89
|
+
sendRequest();
|
|
105
90
|
}, poll);
|
|
106
91
|
|
|
107
|
-
useEffect(
|
|
108
|
-
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
return () => {
|
|
109
94
|
setUnmounted(true);
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
[]
|
|
114
|
-
);
|
|
95
|
+
cancelActiveRequest();
|
|
96
|
+
};
|
|
97
|
+
}, []);
|
|
115
98
|
|
|
116
99
|
return {
|
|
117
|
-
pending,
|
|
100
|
+
pending: pending1 || pending2,
|
|
118
101
|
error,
|
|
119
102
|
data,
|
|
120
|
-
setPending,
|
|
121
|
-
setError,
|
|
122
|
-
setData,
|
|
123
|
-
cancelRequest: cancelActiveRequest,
|
|
124
103
|
sendRequest,
|
|
104
|
+
cancelRequest: cancelActiveRequest,
|
|
125
105
|
};
|
|
126
106
|
}
|
|
127
107
|
|
|
128
|
-
|
|
108
|
+
export default useAsyncFetch;
|
package/useInterval.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
|
|
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(
|
|
4
|
+
const savedCallback = useRef(() => {});
|
|
9
5
|
|
|
10
6
|
useEffect(() => {
|
|
11
7
|
savedCallback.current = callback;
|
|
12
8
|
});
|
|
13
9
|
|
|
14
10
|
useEffect(() => {
|
|
15
|
-
if (poll
|
|
11
|
+
if (!poll) return;
|
|
16
12
|
const tick = () => savedCallback.current();
|
|
17
13
|
const id = setInterval(tick, poll);
|
|
18
|
-
return () =>
|
|
14
|
+
return () => {
|
|
15
|
+
clearInterval(id);
|
|
16
|
+
};
|
|
19
17
|
}, [poll]);
|
|
20
18
|
}
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
export default useInterval;
|
|
21
|
+
|
|
22
|
+
// https://github.com/Hermanya/use-interval/blob/master/src/index.tsx
|