miolo-react 3.0.0-beta.191 → 3.0.0-beta.192

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miolo-react",
3
- "version": "3.0.0-beta.191",
3
+ "version": "3.0.0-beta.192",
4
4
  "description": "React utils for miolo",
5
5
  "author": "Donato Lorenzo <donato@afialapis.com>",
6
6
  "contributors": [
@@ -30,6 +30,7 @@
30
30
  "prepublishOnly": "npm run lint"
31
31
  },
32
32
  "dependencies": {
33
+ "idb-keyval": "^6.2.2",
33
34
  "miolo-cli": "../miolo-cli"
34
35
  },
35
36
  "peerDependencies": {
@@ -2,6 +2,14 @@ import { useCallback, useEffect, useMemo, useState } from "react"
2
2
  import getSsrDataFromContext from "./getSsrDataFromContext.mjs"
3
3
  import usePropsCheck from "./usePropsCheck.mjs"
4
4
 
5
+ const makeSerializable = (obj) => {
6
+ try {
7
+ return JSON.parse(JSON.stringify(obj))
8
+ } catch (e) {
9
+ return obj
10
+ }
11
+ }
12
+
5
13
  const useSsrDataOrReload = (context, miolo, name, options) => {
6
14
  const { fetcher } = miolo
7
15
  const {
@@ -11,7 +19,9 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
11
19
  params = undefined,
12
20
  modifier = undefined,
13
21
  effect = undefined,
14
- model = undefined
22
+ model = undefined,
23
+ cache = true,
24
+ ttl = undefined
15
25
  } = options
16
26
 
17
27
  usePropsCheck(loader, effect, modifier)
@@ -47,8 +57,17 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
47
57
  setSsrData(parseData(data))
48
58
  setStatus("loaded")
49
59
  setError(undefined)
60
+ if (cache === true) {
61
+ if (typeof window !== "undefined") {
62
+ import("idb-keyval").then(({ set }) => {
63
+ set(`ssr-cache-${name}`, { data: makeSerializable(data), ts: Date.now() }).catch(
64
+ () => {}
65
+ )
66
+ })
67
+ }
68
+ }
50
69
  },
51
- [parseData]
70
+ [parseData, name, cache]
52
71
  )
53
72
 
54
73
  const refreshSsrData = useCallback(async () => {
@@ -59,42 +78,113 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
59
78
  setStatus("loading")
60
79
  setError(undefined)
61
80
 
81
+ let newData
82
+
62
83
  if (loader !== undefined) {
63
- const nSsrData = await loader(context, fetcher)
64
- setSsrData(parseData(nSsrData))
84
+ newData = await loader(context, fetcher)
65
85
  } else {
66
86
  if (!url) {
67
87
  setError(`No url provided for ${name}`)
68
88
  } else {
69
89
  const resp = await fetcher.get(url, params)
70
90
  if (resp.ok) {
71
- setSsrData(parseData(resp?.data))
91
+ newData = resp?.data
72
92
  } else {
73
- setError(resp?.error || "Unknonwn error")
93
+ setError(resp?.error || "Unknown error")
74
94
  }
75
95
  }
76
96
  }
97
+
98
+ if (newData !== undefined) {
99
+ if (cache === true) {
100
+ if (typeof window !== "undefined") {
101
+ try {
102
+ const { set } = await import("idb-keyval")
103
+ await set(`ssr-cache-${name}`, { data: makeSerializable(newData), ts: Date.now() })
104
+ } catch (err) {
105
+ console.error(err)
106
+ }
107
+ }
108
+ }
109
+ setSsrData(parseData(newData))
110
+ }
111
+
77
112
  setStatus("loaded")
78
- }, [status, context, fetcher, loader, url, params, parseData, name])
113
+ }, [status, context, fetcher, loader, url, params, parseData, name, cache])
79
114
 
80
115
  useEffect(() => {
81
- try {
82
- if (status === "idle") {
83
- const changed =
84
- effect === undefined ||
85
- (typeof effect === "function" && effect() === true) ||
86
- effect === true
87
- if (changed === true) {
88
- refreshSsrData()
116
+ let mounted = true
117
+
118
+ const loadData = async () => {
119
+ if (!mounted) return
120
+
121
+ try {
122
+ if (status === "idle") {
123
+ const changed =
124
+ effect === undefined ||
125
+ (typeof effect === "function" && effect() === true) ||
126
+ effect === true
127
+
128
+ if (changed === true) {
129
+ let cached = null
130
+ if (cache === true) {
131
+ if (typeof window !== "undefined") {
132
+ try {
133
+ const { get } = await import("idb-keyval")
134
+ cached = await get(`ssr-cache-${name}`)
135
+ } catch (err) {
136
+ console.error(err)
137
+ }
138
+ }
139
+ }
140
+
141
+ if (cached && cached.data !== undefined) {
142
+ setSsrData(parseData(cached.data))
143
+
144
+ if (ttl !== undefined && Date.now() - cached.ts > ttl * 1000) {
145
+ refreshSsrData()
146
+ } else {
147
+ setStatus("loaded")
148
+ }
149
+ } else {
150
+ refreshSsrData()
151
+ }
152
+ }
89
153
  }
90
- }
91
- } catch (_) {}
92
- }, [status, refreshSsrData, effect])
154
+ } catch (_) {}
155
+ }
156
+
157
+ loadData()
158
+
159
+ return () => {
160
+ mounted = false
161
+ }
162
+ }, [status, refreshSsrData, effect, name, ttl, parseData, cache])
163
+
164
+ useEffect(() => {
165
+ if (ssrDataFromContext !== undefined && typeof window !== "undefined") {
166
+ import("idb-keyval").then(({ set }) => {
167
+ set(`ssr-cache-${name}`, {
168
+ data: makeSerializable(ssrDataFromContext),
169
+ ts: Date.now()
170
+ }).catch(() => {})
171
+ })
172
+ }
173
+ }, [ssrDataFromContext, name])
174
+
175
+ const invalidate = useCallback(() => {
176
+ if (typeof window !== "undefined") {
177
+ import("idb-keyval").then(({ del }) => {
178
+ del(`ssr-cache-${name}`).catch(() => {})
179
+ })
180
+ }
181
+ }, [name])
93
182
 
94
183
  return {
95
184
  data: ssrData,
96
185
  setData: updateSsrData,
97
186
  refresh: refreshSsrData,
187
+ invalidate,
98
188
  error,
99
189
  ok: error === undefined,
100
190
  ready: status === "loaded"