async-fetch 0.2.6 → 0.2.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 CHANGED
@@ -56,9 +56,10 @@ The minimum requirement for the hook is a url string as the first argument. The
56
56
  | initialError | Any | Initial state for the error constant. | |
57
57
  | deps | Array | List of dependencies to run the request on. | |
58
58
  | poll | Number | Number of milliseconds to wait for polling requests. | |
59
+ | cachetime | Number | Number of milliseconds to cache responses for. | 60000 |
60
+ | timeout | Number | Number of milliseconds to wait before canceling the request. | 30000 |
59
61
  | ignoreCleanup | Boolean | Whether or not the hook should cleanup on component unmount. | |
60
62
  | ignoreRequest | Boolean | Whether or not the request should send. | |
61
- | timeout | Number | Number of milliseconds to wait before canceling the request. | 30000 |
62
63
  | query | Object | JSON object to append to the url as query params. | |
63
64
  | params | Object | JSON object to append to the url as query params. | |
64
65
  | data | Object | JSON object to send in the request body. | |
@@ -77,7 +78,3 @@ The minimum requirement for the hook is a url string as the first argument. The
77
78
  | data | Any | The response data. |
78
79
  | sendRequest | Function | Function to send the request manually. |
79
80
  | cancelRequest | Function | Function to cancel the request manually. |
80
-
81
- ### Next.js
82
-
83
- For the hook to work properly in a Next.js project you must turn `reactStrictMode` to false in your `next.config.js`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "async-fetch",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Use fetch asynchronously for requests within React components.",
5
5
  "main": "useAsyncFetch.js",
6
6
  "type": "module",
package/useAsyncFetch.js CHANGED
@@ -1,19 +1,21 @@
1
1
  import { useState, useEffect } from "react";
2
+ import useCache from "./useCache.js";
2
3
  import useInterval from "./useInterval.js";
3
4
 
4
- function useAsyncFetch(url, props = {}) {
5
+ function useAsyncFetch(path, props = {}) {
5
6
  const {
6
7
  initialPending,
7
8
  initialData,
8
9
  initialError,
9
10
  deps = [],
10
11
  poll,
12
+ cachetime = 60000, // 1 minute.
13
+ timeout = 30000, // 5 minutes.
11
14
  ignoreCleanup,
12
15
  ignoreRequest,
13
- timeout = 30000,
14
- data: data2,
15
16
  query,
16
17
  params,
18
+ data: data2,
17
19
  parser = "json",
18
20
  onStart,
19
21
  onSuccess,
@@ -34,13 +36,15 @@ function useAsyncFetch(url, props = {}) {
34
36
 
35
37
  const [unmounted, setUnmounted] = useState(false);
36
38
 
39
+ const cache = useCache(cachetime);
40
+
37
41
  useEffect(() => {
38
42
  return cleanupRequest;
39
43
  }, []);
40
44
 
41
45
  useEffect(() => {
42
- sendRequest();
43
- }, [url, query, params, data2, ...deps]);
46
+ sendRequest("USE_CACHE");
47
+ }, [path, ...deps]);
44
48
 
45
49
  useInterval(() => {
46
50
  sendRequest();
@@ -57,10 +61,11 @@ function useAsyncFetch(url, props = {}) {
57
61
  }
58
62
  }
59
63
 
60
- async function sendRequest() {
61
- if (!url) throw new Error("URL is required.");
64
+ async function sendRequest(constant) {
65
+ if (!path) throw new Error("URL is required.");
62
66
 
63
- if (typeof url !== "string") throw new Error("URL must be of type string.");
67
+ if (typeof path !== "string")
68
+ throw new Error("URL must be of type string.");
64
69
 
65
70
  if (ignoreRequest !== true) {
66
71
  const controller = new AbortController();
@@ -72,6 +77,13 @@ function useAsyncFetch(url, props = {}) {
72
77
  }, timeout);
73
78
 
74
79
  try {
80
+ let q = "";
81
+
82
+ if (query || params) {
83
+ if (!path.endsWith("?")) q += "?";
84
+ q += new URLSearchParams(query || params).toString();
85
+ }
86
+
75
87
  const contentType =
76
88
  fetchProps.headers?.["Content-Type"] ||
77
89
  fetchProps.headers?.["content-type"];
@@ -82,36 +94,42 @@ function useAsyncFetch(url, props = {}) {
82
94
  fetchProps.body = JSON.stringify(data2);
83
95
  }
84
96
 
85
- if (query || params) {
86
- url += "?" + new URLSearchParams(query || params).toString();
87
- }
88
-
89
97
  if (!unmounted) {
90
- if (onStart) onStart();
91
98
  if (pending) {
92
99
  setPending2(true);
93
100
  } else setPending(true);
94
101
  setError();
95
102
  cancelRequest();
96
103
  setCancelSource(controller);
104
+ if (onStart) onStart();
97
105
  }
98
106
 
99
- const response = await fetch(url, fetchProps);
107
+ const url = path + q;
108
+
109
+ const cachedResponse =
110
+ constant === "USE_CACHE" && cache.get(url, fetchProps);
111
+
112
+ let parsedResponse = cachedResponse;
100
113
 
101
- if (!response.ok)
102
- throw new Error(
103
- JSON.stringify({
104
- code: response.status,
105
- text: response.statusText,
106
- response: await response.text(),
107
- })
108
- );
114
+ if (!parsedResponse) {
115
+ const response = await fetch(url, fetchProps);
109
116
 
110
- const parsedResponse = await response[parser]();
117
+ if (!response.ok)
118
+ throw new Error(
119
+ JSON.stringify({
120
+ code: response.status,
121
+ text: response.statusText,
122
+ response: await response.text(),
123
+ })
124
+ );
125
+
126
+ parsedResponse = await response[parser]();
127
+ }
111
128
 
112
129
  if (!unmounted) {
113
- if (onSuccess) onSuccess(parsedResponse);
114
130
  setData(parsedResponse);
131
+ if (onSuccess) onSuccess(parsedResponse);
132
+ if (!cachedResponse) cache.set(url, fetchProps, parsedResponse);
115
133
  }
116
134
  } catch (e) {
117
135
  if (!unmounted && e.name !== "AbortError") {
@@ -122,16 +140,16 @@ function useAsyncFetch(url, props = {}) {
122
140
  } catch {
123
141
  error = { response: e.toString(), text: e.toString() };
124
142
  }
125
- if (onFail) onFail(error);
126
143
  setError(error);
144
+ if (onFail) onFail(error);
127
145
  }
128
146
  } finally {
129
147
  clearTimeout(requestTimeout);
130
148
  if (!unmounted) {
131
- if (onFinish) onFinish();
132
149
  if (pending) {
133
150
  setPending2();
134
151
  } else setPending();
152
+ if (onFinish) onFinish();
135
153
  }
136
154
  }
137
155
  }
package/useCache.js ADDED
@@ -0,0 +1,33 @@
1
+ import useInterval from "./useInterval.js";
2
+
3
+ const cache = {};
4
+
5
+ function useCache(cachetime) {
6
+ useInterval(() => {
7
+ for (let [key, value] of Object.entries(cache))
8
+ if (value.timestamp + cachetime < new Date().getTime()) delete cache[key];
9
+ }, cachetime);
10
+
11
+ function makeKey(url, fetchProps) {
12
+ return typeof fetchProps.body === "string" ? url + fetchProps.body : url;
13
+ }
14
+
15
+ function get(url, fetchProps) {
16
+ if (cachetime) {
17
+ const key = makeKey(url, fetchProps);
18
+ return cache[key]?.response;
19
+ }
20
+ }
21
+
22
+ function set(url, fetchProps, response) {
23
+ if (cachetime) {
24
+ const key = makeKey(url, fetchProps);
25
+ const payload = { timestamp: new Date().getTime(), response };
26
+ cache[key] = payload;
27
+ }
28
+ }
29
+
30
+ return { get, set };
31
+ }
32
+
33
+ export default useCache;