miolo-react 3.0.0-beta.167 → 3.0.0-beta.168

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.167",
3
+ "version": "3.0.0-beta.168",
4
4
  "description": "React utils for miolo",
5
5
  "author": "Donato Lorenzo <donato@afialapis.com>",
6
6
  "contributors": [
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect, useState } from "react"
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react"
2
2
  import getSsrDataFromContext from "./getSsrDataFromContext.mjs"
3
3
 
4
4
  const useSsrDataOrReload = (context, miolo, name, options) => {
@@ -13,7 +13,14 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
13
13
  model = undefined
14
14
  } = options
15
15
 
16
- const _parseData = useCallback(
16
+ const prevLoader = useRef(loader)
17
+ const prevEffect = useRef(effect)
18
+ const loaderChangeCount = useRef(0)
19
+ const effectChangeCount = useRef(0)
20
+ const loaderChangeTime = useRef(0)
21
+ const effectChangeTime = useRef(0)
22
+
23
+ const parseData = useCallback(
17
24
  (value) => {
18
25
  let parsed = value
19
26
  if (model !== undefined) {
@@ -27,58 +34,109 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
27
34
  [modifier, model]
28
35
  )
29
36
 
30
- const ssrDataFromContext = getSsrDataFromContext(context, name)
37
+ const ssrDataFromContext = useMemo(() => {
38
+ return getSsrDataFromContext(context, name)
39
+ }, [context, name])
40
+
31
41
  const [ssrData, setSsrData] = useState(
32
- _parseData(ssrDataFromContext !== undefined ? ssrDataFromContext : defval)
42
+ parseData(ssrDataFromContext !== undefined ? ssrDataFromContext : defval)
33
43
  )
34
44
 
35
- const [needToRefresh, setNeedToRefresh] = useState(ssrDataFromContext === undefined)
36
- const [status, setStatus] = useState(needToRefresh ? "idle" : "loaded")
45
+ const [status, setStatus] = useState(ssrDataFromContext !== undefined ? "loaded" : "idle")
37
46
  const [error, setError] = useState(undefined)
38
47
 
48
+ const updateSsrData = useCallback(
49
+ (data) => {
50
+ setStatus("loading")
51
+ setSsrData(parseData(data))
52
+ setStatus("loaded")
53
+ setError(undefined)
54
+ },
55
+ [parseData]
56
+ )
57
+
39
58
  const refreshSsrData = useCallback(async () => {
59
+ if (status === "loading") {
60
+ return
61
+ }
62
+
40
63
  setStatus("loading")
64
+ setError(undefined)
65
+
41
66
  if (loader !== undefined) {
42
67
  const nSsrData = await loader(context, fetcher)
43
- setSsrData(_parseData(nSsrData))
44
- setStatus("loaded")
45
- setError(undefined)
68
+ setSsrData(parseData(nSsrData))
46
69
  } else {
47
70
  if (!url) {
48
71
  setError(`No url provided for ${name}`)
49
72
  } else {
50
73
  const resp = await fetcher.get(url, params)
51
74
  if (resp.ok) {
52
- setSsrData(_parseData(resp?.data))
53
- setStatus("loaded")
54
- setError(undefined)
75
+ setSsrData(parseData(resp?.data))
55
76
  } else {
56
77
  setError(resp?.error || "Unknonwn error")
57
- setStatus("loaded")
58
78
  }
59
79
  }
60
80
  }
61
- }, [context, fetcher, loader, url, params, _parseData, name])
81
+ setStatus("loaded")
82
+ }, [status, context, fetcher, loader, url, params, parseData, name])
83
+
84
+ useEffect(() => {
85
+ if (prevLoader.current !== undefined && prevLoader.current !== loader) {
86
+ const now = Date.now()
87
+ // Si el cambio ocurrió rápido (<100ms desde el último cambio), sumamos al contador continuo
88
+ if (now - loaderChangeTime.current < 100) {
89
+ loaderChangeCount.current += 1
90
+ if (loaderChangeCount.current >= 4) {
91
+ console.warn(
92
+ "🚨 [miolo][useSsrDataOrReload]: 'options.loader' varies too frequently. Wrap it in a useCallback!"
93
+ )
94
+ }
95
+ } else {
96
+ // Ha pasado suficiente tiempo como para ser un cambio humano/aislado
97
+ loaderChangeCount.current = 1
98
+ }
99
+ loaderChangeTime.current = now
100
+ }
101
+ prevLoader.current = loader
102
+ }) // Evalúa en cada render
103
+
104
+ useEffect(() => {
105
+ if (prevEffect.current !== undefined && prevEffect.current !== effect) {
106
+ const now = Date.now()
107
+ if (now - effectChangeTime.current < 100) {
108
+ effectChangeCount.current += 1
109
+ if (effectChangeCount.current >= 4) {
110
+ console.warn(
111
+ "🚨 [miolo][useSsrDataOrReload]: 'options.effect' varies too frequently. Wrap it in a useMemo or useCallback!"
112
+ )
113
+ }
114
+ } else {
115
+ effectChangeCount.current = 1
116
+ }
117
+ effectChangeTime.current = now
118
+ }
119
+ prevEffect.current = effect
120
+ }) // Evalúa en cada render
62
121
 
63
122
  useEffect(() => {
64
123
  try {
65
- if (needToRefresh) {
66
- const changed = effect === undefined || effect.check()
67
- if (changed) {
68
- setNeedToRefresh(false)
124
+ if (status === "idle") {
125
+ const changed = effect?.() === true
126
+ if (changed === true) {
69
127
  refreshSsrData()
70
128
  }
71
129
  }
72
130
  } catch (_) {}
73
- }, [needToRefresh, refreshSsrData, effect, ...(effect?.deps || [])])
131
+ }, [status, refreshSsrData, effect])
74
132
 
75
133
  return {
76
134
  data: ssrData,
77
- setData: (data) => setSsrData(_parseData(data)),
135
+ setData: updateSsrData,
78
136
  refresh: refreshSsrData,
79
137
  error,
80
138
  ok: error === undefined,
81
- ready: status === "loaded" || status === "error"
139
+ ready: status === "loaded"
82
140
  }
83
141
  }
84
142