@dr.pogodin/react-global-state 0.6.3 → 0.6.6

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
@@ -257,5 +257,82 @@ of some, or all async data at the server side.
257
257
  }
258
258
  ```
259
259
 
260
+ ### Frequently Asked Questions
261
+
262
+ - _Does React Global State library avoid unnecessary component re-renders when values updated in the global state are irrelevant to those components?_
263
+
264
+ Yes, it does avoid unnecessary re-renders of the component tree. A component
265
+ relying on `some.path` in the global state is re-rendered only when the value
266
+ at this path, or its sub-path has changed; _i.e._ it will be re-rendered if
267
+ the value at `some.path` has changed, and it will be re-rendered if the value
268
+ at `some.path.sub.path` has changed.
269
+
270
+ - _How would you describe your use case compared to another React global state library, e.g. [Valtio](https://www.npmjs.com/package/valtio)?_
271
+
272
+ 1. React Global State is designed to follow the standard React API as close
273
+ as possible. _E.g._ if some component relies on the local state:
274
+ ```jsx
275
+ const [value, setValue] = useState(initialState);
276
+ ```
277
+ to move that value to the global state (or _vice versa_) one only needs to
278
+ replace the hook with
279
+ ```jsx
280
+ const [value, setValue] = useGlobalState(path, initialState);
281
+ ```
282
+ The [useGlobalState()] hook takes care to follow all edge cases of the
283
+ standard [useState()]: `setValue` setter identity is stable (does not
284
+ change on re-renders), functional updates and lazy initial state are
285
+ supported.
286
+
287
+ Other libraries tend to re-invent the wheel, introducing their own APIs,
288
+ which (i) should be learned and understood; (ii) do complicate migration
289
+ of components between the local and global state, should it be needed in
290
+ a course of app development / prototyping.
291
+
292
+ 2. When it comes to async data in the global state other libraries tend to
293
+ offer only a very basic supported, often relying on experimental or internal
294
+ React mechanics.
295
+
296
+ React Global State, [useAsyncData()] and [useAsyncCollection()] hooks in
297
+ particular, implements async data fetching and management features: when
298
+ multiple components use these hooks to load async data to the same global
299
+ state path the library takes care to do the actual loading just once, and
300
+ then keep the data without reloading until their age reaches (configurable)
301
+ max age. There is an automated garbage collection of expired, non-used
302
+ async data from the global state; there is server-side rendering (SSR)
303
+ support, with suggested high-level setup taking care that all async data
304
+ loaded using [useAsyncData()] and [useAsyncCollection()] hooks will be
305
+ automatically loaded and used in server-side renders (still allowing to
306
+ opt-out of that for individual hooks, and timeout server-side fetching of
307
+ data that take too long to arrive, in which case the library will fetch
308
+ such data client-side). It does not rely on experimental React APIs to
309
+ achieve its functionality, it only uses current public APIs.
310
+
311
+ For me the support of async data fetching into the global state and their
312
+ further management with out-of-the-box SSR support was the primary
313
+ motivation to create React Global State. There are many other global state
314
+ React libraries, but I was not able to find any that would cover the async
315
+ data handling with that ease I believed was possible. The secondary
316
+ motivation was that existing global state libraries either had
317
+ the shortcoming of unnecessary component re-renders when data irrelevant
318
+ to them where updated in the global state, or introduced their
319
+ own APIs, where following the standard React APIs for local state looks
320
+ to me a way more convenient approach.
321
+
322
+ - _Is React Global State library production ready (considering the current version number 0.y.z)?_
323
+
324
+ Yes. I personally use it in production for all my commercial and personal
325
+ React projects for over an year. I just don't feel like to call it v1 until
326
+ a reasonable adoption by 3rd party developers, and any API improvements that
327
+ may come out of community experience.
328
+
260
329
  [Library Reference](https://dr.pogodin.studio/docs/react-global-state/index.html) •
261
330
  [Blog Article](https://dr.pogodin.studio/dev-blog/the-global-state-in-react-designed-right)
331
+
332
+ [useAsyncCollection()]: https://dr.pogodin.studio/docs/react-global-state/docs/api/hooks/useasynccollection
333
+ [useAsyncData()]: https://dr.pogodin.studio/docs/react-global-state/docs/api/hooks/useasyncdata
334
+ [useGlobalState()]: https://dr.pogodin.studio/docs/react-global-state/docs/api/hooks/useglobalstate
335
+ [useState()]: https://reactjs.org/docs/hooks-reference.html#usestate
336
+
337
+ [functional updates]: https://reactjs.org/docs/hooks-reference.html#functional-updates
338
+ [lazy initial state]: https://reactjs.org/docs/hooks-reference.html#functional-updates
@@ -23,9 +23,7 @@ function fullPath(statePath) {
23
23
 
24
24
  class GlobalState {
25
25
  /**
26
- * @class GlobalState
27
- * @classdesc Represents global state objects.
28
- * @desc Creates a new global state object.
26
+ * Creates a new global state object.
29
27
  * @param {any} [initialState] Intial global state content.
30
28
  * @param {SsrContext} [ssrContext] Server-side rendering context.
31
29
  */
@@ -55,9 +53,7 @@ class GlobalState {
55
53
 
56
54
  }
57
55
  /**
58
- * @instance
59
- * @memberof GlobalState
60
- * @desc Gets the value at given `path` of global state. If `path` is null or
56
+ * Gets the value at given `path` of global state. If `path` is null or
61
57
  * undefined, the entire state object is returned.
62
58
  * @param {string} [path] Dot-delimitered state path. If not given, entire
63
59
  * global state content is returned.
@@ -69,9 +65,7 @@ class GlobalState {
69
65
  return (0, _lodash.get)(this, fullPath(path));
70
66
  }
71
67
  /**
72
- * @instance
73
- * @memberof GlobalState
74
- * @desc Writes the `value` to given global state `path`.
68
+ * Writes the `value` to given global state `path`.
75
69
  * @param {string} [path] Dot-delimitered state path. If not given, entire
76
70
  * global state content is replaced by the `value`.
77
71
  * @param {any} value The value.
@@ -129,9 +123,7 @@ class GlobalState {
129
123
  return value;
130
124
  }
131
125
  /**
132
- * @instance
133
- * @memberof GlobalState
134
- * @desc Unsubscribes `callback` from watching state updates; no operation if
126
+ * Unsubscribes `callback` from watching state updates; no operation if
135
127
  * `callback` is not subscribed to the state updates.
136
128
  * @param {function} callback
137
129
  * @throws if {@link SsrContext} is attached to the state instance: the state
@@ -152,9 +144,7 @@ class GlobalState {
152
144
  }
153
145
  }
154
146
  /**
155
- * @instance
156
- * @memberof GlobalState
157
- * @desc Subscribes `callback` to watch state updates; no operation if
147
+ * Subscribes `callback` to watch state updates; no operation if
158
148
  * `callback` is already subscribed to this state instance.
159
149
  * @param {function} callback It will be called without any arguments every
160
150
  * time the state content changes (note, howhever, separate state updates can
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/GlobalState.js"],"names":["ERR_NO_SSR_WATCH","fullPath","statePath","GlobalState","constructor","initialState","ssrContext","state","nextNotifierId","watchers","dirty","pending","process","env","NODE_ENV","msg","console","groupCollapsed","log","groupEnd","get","path","set","value","p","pos","pathSegments","i","length","seg","next","setTimeout","forEach","w","unWatch","callback","Error","indexOf","pop","watch","push"],"mappings":";;;;;;;AAAA;;AAUA;;AAEA,MAAMA,gBAAgB,GAAG,gDAAzB;AAEA;AACA;AACA;AACA;AACA;AACA;;AACA,SAASC,QAAT,CAAkBC,SAAlB,EAA6B;AAC3B,SAAO,mBAAMA,SAAN,IAAmB,OAAnB,GAA8B,SAAQA,SAAU,EAAvD;AACD;;AAEc,MAAMC,WAAN,CAAkB;AAC/B;AACF;AACA;AACA;AACA;AACA;AACA;AACEC,EAAAA,WAAW,CAACC,YAAD,EAAeC,UAAf,EAA2B;AACpC;AACA,SAAKC,KAAL,GAAa,uBAAUF,YAAV,CAAb;AACA,SAAKG,cAAL,GAAsB,IAAtB;AACA,SAAKC,QAAL,GAAgB,EAAhB;;AAEA,QAAIH,UAAJ,EAAgB;AACdA,MAAAA,UAAU,CAACI,KAAX,GAAmB,KAAnB;AACAJ,MAAAA,UAAU,CAACK,OAAX,GAAqB,EAArB;AACAL,MAAAA,UAAU,CAACC,KAAX,GAAmB,KAAKA,KAAxB;AACA,WAAKD,UAAL,GAAkBA,UAAlB;AACD;;AAED,QAAIM,OAAO,CAACC,GAAR,CAAYC,QAAZ,KAAyB,YAAzB,IAAyC,yBAA7C,EAA4D;AAC1D;AACA,UAAIC,GAAG,GAAG,8BAAV;AACA,UAAIT,UAAJ,EAAgBS,GAAG,IAAI,aAAP;AAChBC,MAAAA,OAAO,CAACC,cAAR,CAAuBF,GAAvB;AACAC,MAAAA,OAAO,CAACE,GAAR,CAAY,gBAAZ,EAA8B,uBAAUb,YAAV,CAA9B;AACAW,MAAAA,OAAO,CAACG,QAAR;AACA;AACD;AACD;;AACD;AAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACEC,EAAAA,GAAG,CAACC,IAAD,EAAO;AACR,WAAO,iBAAI,IAAJ,EAAUpB,QAAQ,CAACoB,IAAD,CAAlB,CAAP;AACD;AAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACEC,EAAAA,GAAG,CAACD,IAAD,EAAOE,KAAP,EAAc;AACf,UAAMC,CAAC,GAAGvB,QAAQ,CAACoB,IAAD,CAAlB;;AACA,QAAIE,KAAK,KAAK,iBAAI,IAAJ,EAAUC,CAAV,CAAd,EAA4B;AAC1B,UAAIZ,OAAO,CAACC,GAAR,CAAYC,QAAZ,KAAyB,YAAzB,IAAyC,yBAA7C,EAA4D;AAC1D;AACAE,QAAAA,OAAO,CAACC,cAAR,CACG,mCAAkCI,IAAI,IAAI,EAAG,GADhD;AAGAL,QAAAA,OAAO,CAACE,GAAR,CAAY,YAAZ,EAA0B,uBAAUK,KAAV,CAA1B;AACA;AACD;;AACD,UAAIE,GAAG,GAAG,IAAV;AACA,YAAMC,YAAY,GAAG,oBAAOF,CAAP,CAArB;;AACA,WAAK,IAAIG,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAGD,YAAY,CAACE,MAAb,GAAsB,CAA1C,EAA6CD,CAAC,IAAI,CAAlD,EAAqD;AACnD,cAAME,GAAG,GAAGH,YAAY,CAACC,CAAD,CAAxB;AACA,cAAMG,IAAI,GAAGL,GAAG,CAACI,GAAD,CAAhB;AACA,YAAI,qBAAQC,IAAR,CAAJ,EAAmBL,GAAG,CAACI,GAAD,CAAH,GAAW,CAAC,GAAGC,IAAJ,CAAX,CAAnB,KACK,IAAI,sBAASA,IAAT,CAAJ,EAAoBL,GAAG,CAACI,GAAD,CAAH,GAAW,EAAE,GAAGC;AAAL,SAAX,CAApB,KACA;AACLL,QAAAA,GAAG,GAAGA,GAAG,CAACI,GAAD,CAAT;AACD,OAlByB,CAoB1B;AACA;AACA;AACA;AACA;;;AACA,uBAAI,IAAJ,EAAUL,CAAV,EAAaD,KAAb;;AAEA,UAAI,KAAKjB,UAAT,EAAqB;AACnB,aAAKA,UAAL,CAAgBI,KAAhB,GAAwB,IAAxB;AACA,aAAKJ,UAAL,CAAgBC,KAAhB,GAAwB,KAAKA,KAA7B;AACD,OAHD,MAGO,IAAI,CAAC,KAAKC,cAAV,EAA0B;AAC/B,aAAKA,cAAL,GAAsBuB,UAAU,CAAC,MAAM;AACrC,eAAKvB,cAAL,GAAsB,IAAtB;AACA,WAAC,GAAG,KAAKC,QAAT,EAAmBuB,OAAnB,CAA4BC,CAAD,IAAOA,CAAC,EAAnC;AACD,SAH+B,CAAhC;AAID;;AACD,UAAIrB,OAAO,CAACC,GAAR,CAAYC,QAAZ,KAAyB,YAAzB,IAAyC,yBAA7C,EAA4D;AAC1D;AACAE,QAAAA,OAAO,CAACE,GAAR,CAAY,YAAZ,EAA0B,uBAAU,KAAKX,KAAf,CAA1B;AACAS,QAAAA,OAAO,CAACG,QAAR;AACA;AACD;AACF;;AACD,WAAOI,KAAP;AACD;AAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACEW,EAAAA,OAAO,CAACC,QAAD,EAAW;AAChB,QAAI,KAAK7B,UAAT,EAAqB,MAAM,IAAI8B,KAAJ,CAAUpC,gBAAV,CAAN;AACrB,UAAM;AAAES,MAAAA;AAAF,QAAe,IAArB;AACA,UAAMgB,GAAG,GAAGhB,QAAQ,CAAC4B,OAAT,CAAiBF,QAAjB,CAAZ;;AACA,QAAIV,GAAG,IAAI,CAAX,EAAc;AACZhB,MAAAA,QAAQ,CAACgB,GAAD,CAAR,GAAgBhB,QAAQ,CAACA,QAAQ,CAACmB,MAAT,GAAkB,CAAnB,CAAxB;AACAnB,MAAAA,QAAQ,CAAC6B,GAAT;AACD;AACF;AAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACEC,EAAAA,KAAK,CAACJ,QAAD,EAAW;AACd,QAAI,KAAK7B,UAAT,EAAqB,MAAM,IAAI8B,KAAJ,CAAUpC,gBAAV,CAAN;AACrB,UAAM;AAAES,MAAAA;AAAF,QAAe,IAArB;;AACA,QAAIA,QAAQ,CAAC4B,OAAT,CAAiBF,QAAjB,IAA6B,CAAjC,EAAoC;AAClC1B,MAAAA,QAAQ,CAAC+B,IAAT,CAAcL,QAAd;AACD;AACF;;AA5I8B","sourcesContent":["import {\n cloneDeep,\n get,\n isArray,\n isObject,\n isNil,\n set,\n toPath,\n} from 'lodash';\n\nimport { isDebugMode } from './utils';\n\nconst ERR_NO_SSR_WATCH = 'GlobalState must not be watched at server side';\n\n/**\n * Transform state path into the full path inside GlobalState object.\n * @param {string} statePath\n * @return {string}\n * @ignore\n */\nfunction fullPath(statePath) {\n return isNil(statePath) ? 'state' : `state.${statePath}`;\n}\n\nexport default class GlobalState {\n /**\n * @class GlobalState\n * @classdesc Represents global state objects.\n * @desc Creates a new global state object.\n * @param {any} [initialState] Intial global state content.\n * @param {SsrContext} [ssrContext] Server-side rendering context.\n */\n constructor(initialState, ssrContext) {\n /* eslint-disable no-param-reassign */\n this.state = cloneDeep(initialState);\n this.nextNotifierId = null;\n this.watchers = [];\n\n if (ssrContext) {\n ssrContext.dirty = false;\n ssrContext.pending = [];\n ssrContext.state = this.state;\n this.ssrContext = ssrContext;\n }\n\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n let msg = 'New ReactGlobalState created';\n if (ssrContext) msg += ' (SSR mode)';\n console.groupCollapsed(msg);\n console.log('Initial state:', cloneDeep(initialState));\n console.groupEnd();\n /* eslint-enable no-console */\n }\n /* eslint-enable no-param-reassign */\n }\n\n /**\n * @instance\n * @memberof GlobalState\n * @desc Gets the value at given `path` of global state. If `path` is null or\n * undefined, the entire state object is returned.\n * @param {string} [path] Dot-delimitered state path. If not given, entire\n * global state content is returned.\n * @return {any}\n */\n get(path) {\n return get(this, fullPath(path));\n }\n\n /**\n * @instance\n * @memberof GlobalState\n * @desc Writes the `value` to given global state `path`.\n * @param {string} [path] Dot-delimitered state path. If not given, entire\n * global state content is replaced by the `value`.\n * @param {any} value The value.\n * @return {any} Given `value` itself.\n */\n set(path, value) {\n const p = fullPath(path);\n if (value !== get(this, p)) {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupCollapsed(\n `ReactGlobalState update. Path: \"${path || ''}\"`,\n );\n console.log('New value:', cloneDeep(value));\n /* eslint-enable no-console */\n }\n let pos = this;\n const pathSegments = toPath(p);\n for (let i = 0; i < pathSegments.length - 1; i += 1) {\n const seg = pathSegments[i];\n const next = pos[seg];\n if (isArray(next)) pos[seg] = [...next];\n else if (isObject(next)) pos[seg] = { ...next };\n else break;\n pos = pos[seg];\n }\n\n // TODO: With such naive use of _.set, the state is mutated in place,\n // which may cause tons of unexpected side effects for dependants.\n // It will be better to partially clone the state, so that any existing\n // references are not mutated, while the full deep clonning is also\n // avoided.\n set(this, p, value);\n\n if (this.ssrContext) {\n this.ssrContext.dirty = true;\n this.ssrContext.state = this.state;\n } else if (!this.nextNotifierId) {\n this.nextNotifierId = setTimeout(() => {\n this.nextNotifierId = null;\n [...this.watchers].forEach((w) => w());\n });\n }\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.log('New state:', cloneDeep(this.state));\n console.groupEnd();\n /* eslint-enable no-console */\n }\n }\n return value;\n }\n\n /**\n * @instance\n * @memberof GlobalState\n * @desc Unsubscribes `callback` from watching state updates; no operation if\n * `callback` is not subscribed to the state updates.\n * @param {function} callback\n * @throws if {@link SsrContext} is attached to the state instance: the state\n * watching functionality is intended for client-side (non-SSR) only.\n */\n unWatch(callback) {\n if (this.ssrContext) throw new Error(ERR_NO_SSR_WATCH);\n const { watchers } = this;\n const pos = watchers.indexOf(callback);\n if (pos >= 0) {\n watchers[pos] = watchers[watchers.length - 1];\n watchers.pop();\n }\n }\n\n /**\n * @instance\n * @memberof GlobalState\n * @desc Subscribes `callback` to watch state updates; no operation if\n * `callback` is already subscribed to this state instance.\n * @param {function} callback It will be called without any arguments every\n * time the state content changes (note, howhever, separate state updates can\n * be applied to the state at once, and watching callbacks will be called once\n * after such bulk update).\n * @throws if {@link SsrContext} is attached to the state instance: the state\n * watching functionality is intended for client-side (non-SSR) only.\n */\n watch(callback) {\n if (this.ssrContext) throw new Error(ERR_NO_SSR_WATCH);\n const { watchers } = this;\n if (watchers.indexOf(callback) < 0) {\n watchers.push(callback);\n }\n }\n}\n"],"file":"GlobalState.js"}
1
+ {"version":3,"sources":["../../src/GlobalState.js"],"names":["ERR_NO_SSR_WATCH","fullPath","statePath","GlobalState","constructor","initialState","ssrContext","state","nextNotifierId","watchers","dirty","pending","process","env","NODE_ENV","msg","console","groupCollapsed","log","groupEnd","get","path","set","value","p","pos","pathSegments","i","length","seg","next","setTimeout","forEach","w","unWatch","callback","Error","indexOf","pop","watch","push"],"mappings":"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","sourcesContent":["import {\n cloneDeep,\n get,\n isArray,\n isObject,\n isNil,\n set,\n toPath,\n} from 'lodash';\n\nimport { isDebugMode } from './utils';\n\nconst ERR_NO_SSR_WATCH = 'GlobalState must not be watched at server side';\n\n/**\n * Transform state path into the full path inside GlobalState object.\n * @param {string} statePath\n * @return {string}\n * @ignore\n */\nfunction fullPath(statePath) {\n return isNil(statePath) ? 'state' : `state.${statePath}`;\n}\n\nexport default class GlobalState {\n /**\n * Creates a new global state object.\n * @param {any} [initialState] Intial global state content.\n * @param {SsrContext} [ssrContext] Server-side rendering context.\n */\n constructor(initialState, ssrContext) {\n /* eslint-disable no-param-reassign */\n this.state = cloneDeep(initialState);\n this.nextNotifierId = null;\n this.watchers = [];\n\n if (ssrContext) {\n ssrContext.dirty = false;\n ssrContext.pending = [];\n ssrContext.state = this.state;\n this.ssrContext = ssrContext;\n }\n\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n let msg = 'New ReactGlobalState created';\n if (ssrContext) msg += ' (SSR mode)';\n console.groupCollapsed(msg);\n console.log('Initial state:', cloneDeep(initialState));\n console.groupEnd();\n /* eslint-enable no-console */\n }\n /* eslint-enable no-param-reassign */\n }\n\n /**\n * Gets the value at given `path` of global state. If `path` is null or\n * undefined, the entire state object is returned.\n * @param {string} [path] Dot-delimitered state path. If not given, entire\n * global state content is returned.\n * @return {any}\n */\n get(path) {\n return get(this, fullPath(path));\n }\n\n /**\n * Writes the `value` to given global state `path`.\n * @param {string} [path] Dot-delimitered state path. If not given, entire\n * global state content is replaced by the `value`.\n * @param {any} value The value.\n * @return {any} Given `value` itself.\n */\n set(path, value) {\n const p = fullPath(path);\n if (value !== get(this, p)) {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupCollapsed(\n `ReactGlobalState update. Path: \"${path || ''}\"`,\n );\n console.log('New value:', cloneDeep(value));\n /* eslint-enable no-console */\n }\n let pos = this;\n const pathSegments = toPath(p);\n for (let i = 0; i < pathSegments.length - 1; i += 1) {\n const seg = pathSegments[i];\n const next = pos[seg];\n if (isArray(next)) pos[seg] = [...next];\n else if (isObject(next)) pos[seg] = { ...next };\n else break;\n pos = pos[seg];\n }\n\n // TODO: With such naive use of _.set, the state is mutated in place,\n // which may cause tons of unexpected side effects for dependants.\n // It will be better to partially clone the state, so that any existing\n // references are not mutated, while the full deep clonning is also\n // avoided.\n set(this, p, value);\n\n if (this.ssrContext) {\n this.ssrContext.dirty = true;\n this.ssrContext.state = this.state;\n } else if (!this.nextNotifierId) {\n this.nextNotifierId = setTimeout(() => {\n this.nextNotifierId = null;\n [...this.watchers].forEach((w) => w());\n });\n }\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.log('New state:', cloneDeep(this.state));\n console.groupEnd();\n /* eslint-enable no-console */\n }\n }\n return value;\n }\n\n /**\n * Unsubscribes `callback` from watching state updates; no operation if\n * `callback` is not subscribed to the state updates.\n * @param {function} callback\n * @throws if {@link SsrContext} is attached to the state instance: the state\n * watching functionality is intended for client-side (non-SSR) only.\n */\n unWatch(callback) {\n if (this.ssrContext) throw new Error(ERR_NO_SSR_WATCH);\n const { watchers } = this;\n const pos = watchers.indexOf(callback);\n if (pos >= 0) {\n watchers[pos] = watchers[watchers.length - 1];\n watchers.pop();\n }\n }\n\n /**\n * Subscribes `callback` to watch state updates; no operation if\n * `callback` is already subscribed to this state instance.\n * @param {function} callback It will be called without any arguments every\n * time the state content changes (note, howhever, separate state updates can\n * be applied to the state at once, and watching callbacks will be called once\n * after such bulk update).\n * @throws if {@link SsrContext} is attached to the state instance: the state\n * watching functionality is intended for client-side (non-SSR) only.\n */\n watch(callback) {\n if (this.ssrContext) throw new Error(ERR_NO_SSR_WATCH);\n const { watchers } = this;\n if (watchers.indexOf(callback) < 0) {\n watchers.push(callback);\n }\n }\n}\n"],"file":"GlobalState.js"}
@@ -16,27 +16,9 @@ var _GlobalState = _interopRequireDefault(require("./GlobalState"));
16
16
  var _jsxRuntime = require("react/jsx-runtime");
17
17
 
18
18
  /* eslint-disable react/prop-types */
19
-
20
- /**
21
- * @typedef {object} SsrContext Holds global-state-related information,
22
- * which should be persistent across rendering iterations during server-side
23
- * rendering (SSR). For the first SSR iteration any object, including an empty
24
- * `{}`, may be provided to {@link &lt;GlobalStateProvider&gt;}: in either case
25
- * all its fields listed below will be (re-)initialized as needed, and any other
26
- * fields contained in the object won't be touched by the library (thus, you may
27
- * use it to keep other data you need across SSR iterations, and you can access
28
- * it from React components via {@link getSsrContext} hook).
29
- * @prop {boolean} dirty `true` if the global state has been modified in
30
- * the last SSR iteration; `false` otherwise.
31
- * @prop {Promise[]} pending An array of promises waiting for completion of
32
- * asynchronous state operations (like {@link useAsyncData}), initiated during
33
- * the last SSR iteration.
34
- * @prop {any} state The global state content at the end of last SSR iteration.
35
- */
36
19
  const context = /*#__PURE__*/(0, _react.createContext)();
37
20
  /**
38
- * @category Hooks
39
- * @desc Gets {@link GlobalState} instance from the context. In most cases
21
+ * Gets {@link GlobalState} instance from the context. In most cases
40
22
  * you should use {@link useGlobalState}, and other hooks to interact with
41
23
  * the global state, instead of accessing it directly.
42
24
  * @return {GlobalState}
@@ -84,9 +66,7 @@ function getSsrContext(throwWithoutSsrContext = true) {
84
66
  return ssrContext;
85
67
  }
86
68
  /**
87
- * @category Components
88
- * @name &lt;GlobalStateProvider&gt;
89
- * @desc Provides global state to its children.
69
+ * Provides global state to its children.
90
70
  * @prop {ReactNode} [children] Component children, which will be provided with
91
71
  * the global state, and rendered in place of the provider.
92
72
  * @prop {any} [initialState] Initial content of the global state.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/GlobalStateProvider.jsx"],"names":["context","getGlobalState","globalState","Error","getSsrContext","throwWithoutSsrContext","ssrContext","GlobalStateProvider","children","initialState","stateProxy","state","GlobalState"],"mappings":";;;;;;;;;;;AAmBA;;AAEA;;;;AArBA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA,MAAMA,OAAO,gBAAG,2BAAhB;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AACO,SAASC,cAAT,GAA0B;AAC/B;AACA;AACA;AACA;AACA;;AACA;AACA,QAAMC,WAAW,GAAG,uBAAWF,OAAX,CAApB;AACA;;AACA,MAAI,CAACE,WAAL,EAAkB,MAAM,IAAIC,KAAJ,CAAU,6BAAV,CAAN;AAClB,SAAOD,WAAP;AACD;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACO,SAASE,aAAT,CAAuBC,sBAAsB,GAAG,IAAhD,EAAsD;AAC3D,QAAM;AAAEC,IAAAA;AAAF,MAAiBL,cAAc,EAArC;;AACA,MAAI,CAACK,UAAD,IAAeD,sBAAnB,EAA2C;AACzC,UAAM,IAAIF,KAAJ,CAAU,sBAAV,CAAN;AACD;;AACD,SAAOG,UAAP;AACD;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACe,SAASC,mBAAT,CAA6B;AAC1CC,EAAAA,QAD0C;AAE1CC,EAAAA,YAF0C;AAG1CH,EAAAA,UAH0C;AAI1CI,EAAAA;AAJ0C,CAA7B,EAKZ;AACD,MAAIC,KAAJ,CADC,CAED;AACA;AACA;AACA;;AACA;;AACA,MAAID,UAAU,YAAYE,oBAA1B,EAAuCD,KAAK,GAAGD,UAAR,CAAvC,KACK,IAAIA,UAAJ,EAAgBC,KAAK,GAAGV,cAAc,EAAtB,CAAhB,KACA,CAACU,KAAD,IAAU,qBAAS,IAAIC,oBAAJ,CAAgBH,YAAhB,EAA8BH,UAA9B,CAAT,CAAV;AACL;;AACA,sBACE,qBAAC,OAAD,CAAS,QAAT;AAAkB,IAAA,KAAK,EAAEK,KAAzB;AAAA,cACGH;AADH,IADF;AAKD","sourcesContent":["/* eslint-disable react/prop-types */\n\n/**\n * @typedef {object} SsrContext Holds global-state-related information,\n * which should be persistent across rendering iterations during server-side\n * rendering (SSR). For the first SSR iteration any object, including an empty\n * `{}`, may be provided to {@link &lt;GlobalStateProvider&gt;}: in either case\n * all its fields listed below will be (re-)initialized as needed, and any other\n * fields contained in the object won't be touched by the library (thus, you may\n * use it to keep other data you need across SSR iterations, and you can access\n * it from React components via {@link getSsrContext} hook).\n * @prop {boolean} dirty `true` if the global state has been modified in\n * the last SSR iteration; `false` otherwise.\n * @prop {Promise[]} pending An array of promises waiting for completion of\n * asynchronous state operations (like {@link useAsyncData}), initiated during\n * the last SSR iteration.\n * @prop {any} state The global state content at the end of last SSR iteration.\n */\n\nimport { createContext, useContext, useState } from 'react';\n\nimport GlobalState from './GlobalState';\n\nconst context = createContext();\n\n/**\n * @category Hooks\n * @desc Gets {@link GlobalState} instance from the context. In most cases\n * you should use {@link useGlobalState}, and other hooks to interact with\n * the global state, instead of accessing it directly.\n * @return {GlobalState}\n */\nexport function getGlobalState() {\n // Here Rules of Hooks are violated because \"getGlobalState()\" does not follow\n // convention that hook names should start with use... This is intentional in\n // our case, as getGlobalState() hook is intended for advance scenarious,\n // while the normal interaction with the global state should happen via\n // another hook, useGlobalState().\n /* eslint-disable react-hooks/rules-of-hooks */\n const globalState = useContext(context);\n /* eslint-enable react-hooks/rules-of-hooks */\n if (!globalState) throw new Error('Missing GlobalStateProvider');\n return globalState;\n}\n\n/**\n * @category Hooks\n * @desc Gets SSR context.\n * @param {boolean} [throwWithoutSsrContext=true] If `true` (default),\n * this hook will throw if no SSR context is attached to the global state;\n * set `false` to not throw in such case. In either case the hook will throw\n * if the {@link &lt;GlobalStateProvider&gt;} (hence the state) is missing.\n * @returns {SsrContext} SSR context.\n * @throws\n * - If current component has no parent {@link &lt;GlobalStateProvider&gt;}\n * in the rendered React tree.\n * - If `throwWithoutSsrContext` is `true`, and there is no SSR context attached\n * to the global state provided by {@link &lt;GlobalStateProvider&gt;}.\n */\nexport function getSsrContext(throwWithoutSsrContext = true) {\n const { ssrContext } = getGlobalState();\n if (!ssrContext && throwWithoutSsrContext) {\n throw new Error('No SSR context found');\n }\n return ssrContext;\n}\n\n/**\n * @category Components\n * @name &lt;GlobalStateProvider&gt;\n * @desc Provides global state to its children.\n * @prop {ReactNode} [children] Component children, which will be provided with\n * the global state, and rendered in place of the provider.\n * @prop {any} [initialState] Initial content of the global state.\n * @prop {SsrContext} [ssrContext] Server-side rendering (SSR) context.\n * @prop {boolean|GlobalState} [stateProxy] This option is useful for code\n * splitting and SSR implementation:\n * - If `true`, this provider instance will fetch and reuse the global state\n * from a parent provider.\n * - If `GlobalState` instance, it will be used by this provider.\n * - If not given, a new `GlobalState` instance will be created and used.\n */\nexport default function GlobalStateProvider({\n children,\n initialState,\n ssrContext,\n stateProxy,\n}) {\n let state;\n // Here Rules of Hooks are violated because hooks are called conditionally,\n // however we assume that these properties should not change at runtime, thus\n // the actual hook order is preserved. Probably, it should be handled better,\n // though.\n /* eslint-disable react-hooks/rules-of-hooks */\n if (stateProxy instanceof GlobalState) state = stateProxy;\n else if (stateProxy) state = getGlobalState();\n else [state] = useState(new GlobalState(initialState, ssrContext));\n /* eslint-enable react-hooks/rules-of-hooks */\n return (\n <context.Provider value={state}>\n {children}\n </context.Provider>\n );\n}\n"],"file":"GlobalStateProvider.js"}
1
+ {"version":3,"sources":["../../src/GlobalStateProvider.jsx"],"names":["context","getGlobalState","globalState","Error","getSsrContext","throwWithoutSsrContext","ssrContext","GlobalStateProvider","children","initialState","stateProxy","state","GlobalState"],"mappings":";;;;;;;;;;;AAEA;;AAEA;;;;AAJA;AAMA,MAAMA,OAAO,gBAAG,2BAAhB;AAEA;AACA;AACA;AACA;AACA;AACA;;AACO,SAASC,cAAT,GAA0B;AAC/B;AACA;AACA;AACA;AACA;;AACA;AACA,QAAMC,WAAW,GAAG,uBAAWF,OAAX,CAApB;AACA;;AACA,MAAI,CAACE,WAAL,EAAkB,MAAM,IAAIC,KAAJ,CAAU,6BAAV,CAAN;AAClB,SAAOD,WAAP;AACD;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACO,SAASE,aAAT,CAAuBC,sBAAsB,GAAG,IAAhD,EAAsD;AAC3D,QAAM;AAAEC,IAAAA;AAAF,MAAiBL,cAAc,EAArC;;AACA,MAAI,CAACK,UAAD,IAAeD,sBAAnB,EAA2C;AACzC,UAAM,IAAIF,KAAJ,CAAU,sBAAV,CAAN;AACD;;AACD,SAAOG,UAAP;AACD;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACe,SAASC,mBAAT,CAA6B;AAC1CC,EAAAA,QAD0C;AAE1CC,EAAAA,YAF0C;AAG1CH,EAAAA,UAH0C;AAI1CI,EAAAA;AAJ0C,CAA7B,EAKZ;AACD,MAAIC,KAAJ,CADC,CAED;AACA;AACA;AACA;;AACA;;AACA,MAAID,UAAU,YAAYE,oBAA1B,EAAuCD,KAAK,GAAGD,UAAR,CAAvC,KACK,IAAIA,UAAJ,EAAgBC,KAAK,GAAGV,cAAc,EAAtB,CAAhB,KACA,CAACU,KAAD,IAAU,qBAAS,IAAIC,oBAAJ,CAAgBH,YAAhB,EAA8BH,UAA9B,CAAT,CAAV;AACL;;AACA,sBACE,qBAAC,OAAD,CAAS,QAAT;AAAkB,IAAA,KAAK,EAAEK,KAAzB;AAAA,cACGH;AADH,IADF;AAKD","sourcesContent":["/* eslint-disable react/prop-types */\n\nimport { createContext, useContext, useState } from 'react';\n\nimport GlobalState from './GlobalState';\n\nconst context = createContext();\n\n/**\n * Gets {@link GlobalState} instance from the context. In most cases\n * you should use {@link useGlobalState}, and other hooks to interact with\n * the global state, instead of accessing it directly.\n * @return {GlobalState}\n */\nexport function getGlobalState() {\n // Here Rules of Hooks are violated because \"getGlobalState()\" does not follow\n // convention that hook names should start with use... This is intentional in\n // our case, as getGlobalState() hook is intended for advance scenarious,\n // while the normal interaction with the global state should happen via\n // another hook, useGlobalState().\n /* eslint-disable react-hooks/rules-of-hooks */\n const globalState = useContext(context);\n /* eslint-enable react-hooks/rules-of-hooks */\n if (!globalState) throw new Error('Missing GlobalStateProvider');\n return globalState;\n}\n\n/**\n * @category Hooks\n * @desc Gets SSR context.\n * @param {boolean} [throwWithoutSsrContext=true] If `true` (default),\n * this hook will throw if no SSR context is attached to the global state;\n * set `false` to not throw in such case. In either case the hook will throw\n * if the {@link &lt;GlobalStateProvider&gt;} (hence the state) is missing.\n * @returns {SsrContext} SSR context.\n * @throws\n * - If current component has no parent {@link &lt;GlobalStateProvider&gt;}\n * in the rendered React tree.\n * - If `throwWithoutSsrContext` is `true`, and there is no SSR context attached\n * to the global state provided by {@link &lt;GlobalStateProvider&gt;}.\n */\nexport function getSsrContext(throwWithoutSsrContext = true) {\n const { ssrContext } = getGlobalState();\n if (!ssrContext && throwWithoutSsrContext) {\n throw new Error('No SSR context found');\n }\n return ssrContext;\n}\n\n/**\n * Provides global state to its children.\n * @prop {ReactNode} [children] Component children, which will be provided with\n * the global state, and rendered in place of the provider.\n * @prop {any} [initialState] Initial content of the global state.\n * @prop {SsrContext} [ssrContext] Server-side rendering (SSR) context.\n * @prop {boolean|GlobalState} [stateProxy] This option is useful for code\n * splitting and SSR implementation:\n * - If `true`, this provider instance will fetch and reuse the global state\n * from a parent provider.\n * - If `GlobalState` instance, it will be used by this provider.\n * - If not given, a new `GlobalState` instance will be created and used.\n */\nexport default function GlobalStateProvider({\n children,\n initialState,\n ssrContext,\n stateProxy,\n}) {\n let state;\n // Here Rules of Hooks are violated because hooks are called conditionally,\n // however we assume that these properties should not change at runtime, thus\n // the actual hook order is preserved. Probably, it should be handled better,\n // though.\n /* eslint-disable react-hooks/rules-of-hooks */\n if (stateProxy instanceof GlobalState) state = stateProxy;\n else if (stateProxy) state = getGlobalState();\n else [state] = useState(new GlobalState(initialState, ssrContext));\n /* eslint-enable react-hooks/rules-of-hooks */\n return (\n <context.Provider value={state}>\n {children}\n </context.Provider>\n );\n}\n"],"file":"GlobalStateProvider.js"}
@@ -14,20 +14,7 @@ var _useAsyncData = _interopRequireDefault(require("./useAsyncData"));
14
14
  */
15
15
 
16
16
  /**
17
- * @typedef {function} AsyncCollectionLoader This is the signature of
18
- * `loader` function accepted by {@link useAsyncCollection} hook.
19
- * @param {string} id ID of the collection item to load.
20
- * @param {any} oldData Previously fetched data for this ID, if any. The loader
21
- * does not have to use it, it is provided just for convenience, when the newly
22
- * resolved data may depend on the previously fetched data.
23
- * @returns {Promise<any>} Resolves to data to be stored in the global state
24
- * for the given collection item ID.
25
- */
26
-
27
- /**
28
- * @category Hooks
29
- * @func useAsyncCollection
30
- * @desc Resolves and stores at the given `path` of global state elements of
17
+ * Resolves and stores at the given `path` of global state elements of
31
18
  * an asynchronous data collection. In other words, it is an auxiliar wrapper
32
19
  * around {@link useAsyncData}, which uses a loader which resolves to different
33
20
  * data, based on ID argument passed in, and stores data fetched for different
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useAsyncCollection.js"],"names":["useAsyncCollection","id","path","loader","options","itemPath","oldData"],"mappings":";;;;;;;;;AAIA;;AAJA;AACA;AACA;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,SAASA,kBAAT,CACbC,EADa,EAEbC,IAFa,EAGbC,MAHa,EAIbC,OAAO,GAAG,EAJG,EAKb;AACA,QAAMC,QAAQ,GAAGH,IAAI,GAAI,GAAEA,IAAK,IAAGD,EAAG,EAAjB,GAAqBA,EAA1C;AACA,SAAO,2BAAaI,QAAb,EAAwBC,OAAD,IAAaH,MAAM,CAACF,EAAD,EAAKK,OAAL,CAA1C,EAAyDF,OAAzD,CAAP;AACD","sourcesContent":["/**\n * Loads and uses an item in an async collection.\n */\n\nimport useAsyncData from './useAsyncData';\n\n/**\n * @typedef {function} AsyncCollectionLoader This is the signature of\n * `loader` function accepted by {@link useAsyncCollection} hook.\n * @param {string} id ID of the collection item to load.\n * @param {any} oldData Previously fetched data for this ID, if any. The loader\n * does not have to use it, it is provided just for convenience, when the newly\n * resolved data may depend on the previously fetched data.\n * @returns {Promise<any>} Resolves to data to be stored in the global state\n * for the given collection item ID.\n */\n\n/**\n * @category Hooks\n * @func useAsyncCollection\n * @desc Resolves and stores at the given `path` of global state elements of\n * an asynchronous data collection. In other words, it is an auxiliar wrapper\n * around {@link useAsyncData}, which uses a loader which resolves to different\n * data, based on ID argument passed in, and stores data fetched for different\n * IDs in the state.\n * @param {string} id ID of the collection item to load & use.\n * @param {string} path The global state path where entire collection should be\n * stored.\n * @param {AsyncCollectionLoader} loader A loader function, which takes an\n * ID of data to load, and resolves to the corresponding data.\n * @param {object} [options] Additional options.\n * @param {any[]} [options.deps=[]] An array of dependencies, which trigger\n * data reload when changed. Given dependency changes are watched shallowly\n * (similarly to the standard React's\n * [useEffect()](https://reactjs.org/docs/hooks-reference.html#useeffect)).\n * @param {boolean} [options.noSSR] If `true`, this hook won't load data during\n * server-side rendering.\n * @param {number} [options.garbageCollectAge=maxage] The maximum age of data\n * (in milliseconds), after which they are dropped from the state when the last\n * component referencing them via `useAsyncData()` hook unmounts. Defaults to\n * `maxage` option value.\n * @param {number} [options.maxage=5 x 60 x 1000] The maximum age of\n * data (in milliseconds) acceptable to the hook's caller. If loaded data are\n * older than this value, `null` is returned instead. Defaults to 5 minutes.\n * @param {number} [options.refreshAge=maxage] The maximum age of data\n * (in milliseconds), after which their refreshment will be triggered when\n * any component referencing them via `useAsyncData()` hook (re-)renders.\n * Defaults to `maxage` value.\n * @return {{\n * data: any,\n * loading: boolean,\n * timestamp: number\n * }} Returns an object with three fields: `data` holds the actual result of\n * last `loader` invokation, if any, and if satisfies `maxage` limit; `loading`\n * is a boolean flag, which is `true` if data are being loaded (the hook is\n * waiting for `loader` function resolution); `timestamp` (in milliseconds)\n * is Unix timestamp of related data currently loaded into the global state.\n *\n * Note that loaded data, if any, are stored at the given `path` of global state\n * along with related meta-information, using slightly different state segment\n * structure (see {@link AsyncDataEnvelope}). That segment of the global state\n * can be accessed, and even modified using other hooks,\n * _e.g._ {@link useGlobalState}, but doing so you may interfere with related\n * `useAsyncData()` hooks logic.\n */\nexport default function useAsyncCollection(\n id,\n path,\n loader,\n options = {},\n) {\n const itemPath = path ? `${path}.${id}` : id;\n return useAsyncData(itemPath, (oldData) => loader(id, oldData), options);\n}\n"],"file":"useAsyncCollection.js"}
1
+ {"version":3,"sources":["../../src/useAsyncCollection.js"],"names":["useAsyncCollection","id","path","loader","options","itemPath","oldData"],"mappings":";;;;;;;;;AAIA;;AAJA;AACA;AACA;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,SAASA,kBAAT,CACbC,EADa,EAEbC,IAFa,EAGbC,MAHa,EAIbC,OAAO,GAAG,EAJG,EAKb;AACA,QAAMC,QAAQ,GAAGH,IAAI,GAAI,GAAEA,IAAK,IAAGD,EAAG,EAAjB,GAAqBA,EAA1C;AACA,SAAO,2BAAaI,QAAb,EAAwBC,OAAD,IAAaH,MAAM,CAACF,EAAD,EAAKK,OAAL,CAA1C,EAAyDF,OAAzD,CAAP;AACD","sourcesContent":["/**\n * Loads and uses an item in an async collection.\n */\n\nimport useAsyncData from './useAsyncData';\n\n/**\n * Resolves and stores at the given `path` of global state elements of\n * an asynchronous data collection. In other words, it is an auxiliar wrapper\n * around {@link useAsyncData}, which uses a loader which resolves to different\n * data, based on ID argument passed in, and stores data fetched for different\n * IDs in the state.\n * @param {string} id ID of the collection item to load & use.\n * @param {string} path The global state path where entire collection should be\n * stored.\n * @param {AsyncCollectionLoader} loader A loader function, which takes an\n * ID of data to load, and resolves to the corresponding data.\n * @param {object} [options] Additional options.\n * @param {any[]} [options.deps=[]] An array of dependencies, which trigger\n * data reload when changed. Given dependency changes are watched shallowly\n * (similarly to the standard React's\n * [useEffect()](https://reactjs.org/docs/hooks-reference.html#useeffect)).\n * @param {boolean} [options.noSSR] If `true`, this hook won't load data during\n * server-side rendering.\n * @param {number} [options.garbageCollectAge=maxage] The maximum age of data\n * (in milliseconds), after which they are dropped from the state when the last\n * component referencing them via `useAsyncData()` hook unmounts. Defaults to\n * `maxage` option value.\n * @param {number} [options.maxage=5 x 60 x 1000] The maximum age of\n * data (in milliseconds) acceptable to the hook's caller. If loaded data are\n * older than this value, `null` is returned instead. Defaults to 5 minutes.\n * @param {number} [options.refreshAge=maxage] The maximum age of data\n * (in milliseconds), after which their refreshment will be triggered when\n * any component referencing them via `useAsyncData()` hook (re-)renders.\n * Defaults to `maxage` value.\n * @return {{\n * data: any,\n * loading: boolean,\n * timestamp: number\n * }} Returns an object with three fields: `data` holds the actual result of\n * last `loader` invokation, if any, and if satisfies `maxage` limit; `loading`\n * is a boolean flag, which is `true` if data are being loaded (the hook is\n * waiting for `loader` function resolution); `timestamp` (in milliseconds)\n * is Unix timestamp of related data currently loaded into the global state.\n *\n * Note that loaded data, if any, are stored at the given `path` of global state\n * along with related meta-information, using slightly different state segment\n * structure (see {@link AsyncDataEnvelope}). That segment of the global state\n * can be accessed, and even modified using other hooks,\n * _e.g._ {@link useGlobalState}, but doing so you may interfere with related\n * `useAsyncData()` hooks logic.\n */\nexport default function useAsyncCollection(\n id,\n path,\n loader,\n options = {},\n) {\n const itemPath = path ? `${path}.${id}` : id;\n return useAsyncData(itemPath, (oldData) => loader(id, oldData), options);\n}\n"],"file":"useAsyncCollection.js"}
@@ -74,40 +74,7 @@ async function load(path, loader, globalState, oldData, opIdPrefix = 'C') {
74
74
  }
75
75
  }
76
76
  /**
77
- * @typedef {object} AsyncDataEnvelope This type documents the structure of
78
- * global state segment, created by {@link useAsyncData} hook for storing of
79
- * loaded async data, and associated metadata.
80
- * @prop {any} data The actual loaded data.
81
- * @prop {number} numRefs The count of currently mounted components referencing
82
- * the data via `useAsyncData` hooks.
83
- * @prop {string} operationId A unique ID of the current data loading
84
- * operation, if one is in progress. Changing this ID before the operation
85
- * completes effectively cancels the ongoing operation, and instructs related
86
- * hook to ignore the operation result.
87
- *
88
- * NOTE: Server-side and client-side operation UIDs start with `S` or `C` letter
89
- * respectively. At the client side, if an envelop stores `operationId` starting
90
- * with `S` letter, it is understood as a non-terminated data loading operation
91
- * during SSR, and it is restarted at the client-side in this case.
92
- * @prop {number} timestamp Unix timestamp (in milliseconds) of the most
93
- * recently loaded `data`.
94
- */
95
-
96
- /**
97
- * @typedef {function} AsyncDataLoader This type documents the signature of
98
- * async data loader function, expected by {@link useAsyncData} hook.
99
- * @param {any} oldData Previously loaded data (_i.e._ the data currently stored
100
- * at the global state `path` managed by the corresponding `useAsyncData` hook,
101
- * which are assumed to be resolved from a previous call to the loader).
102
- * The loader does not have to use this argument, it is provided just for
103
- * convenience.
104
- * @return {Promise<any>} Async data to store to the state.
105
- */
106
-
107
- /**
108
- * @category Hooks
109
- * @func useAsyncData
110
- * @desc Resolves asynchronous data, and stores them at given `path` of global
77
+ * Resolves asynchronous data, and stores them at given `path` of global
111
78
  * state. When multiple components rely on asynchronous data at the same `path`,
112
79
  * the data are resolved once, and reused until their age is within specified
113
80
  * bounds. Once the data are stale, the hook allows to refresh them. It also
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useAsyncData.js"],"names":["DEFAULT_MAXAGE","load","path","loader","globalState","oldData","opIdPrefix","process","env","NODE_ENV","console","log","operationId","operationIdPath","set","data","get","state","groupCollapsed","timestamp","Date","now","groupEnd","useAsyncData","options","garbageCollectAge","maxage","refreshAge","undefined","localState","numRefs","ssrContext","noSSR","pending","push","numRefsPath","loadTriggered","charAt","deps","length","loading","Boolean"],"mappings":"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","sourcesContent":["/**\n * Loads and uses async data into the GlobalState path.\n */\n\nimport { cloneDeep } from 'lodash';\nimport { useEffect } from 'react';\nimport { v4 as uuid } from 'uuid';\n\nimport { getGlobalState } from './GlobalStateProvider';\nimport useGlobalState from './useGlobalState';\nimport { isDebugMode } from './utils';\n\nconst DEFAULT_MAXAGE = 5 * 60 * 1000; // 5 minutes.\n\n/**\n * Executes the data loading operation.\n * @param {string} path Data segment path inside the global state.\n * @param {function} loader Data loader.\n * @param {GlobalState} globalState The global state instance.\n * @param {any} [oldData] Optional. Previously fetched data, currently stored in\n * the state, if already fetched by the caller; otherwise, they will be fetched\n * by the load() function itself.\n * @param {string} [opIdPrefix='C'] operationId prefix to use, which should be\n * 'C' at the client-side (default), or 'S' at the server-side (within SSR\n * context).\n * @return {Promise} Resolves once the operation is done.\n * @ignore\n */\nasync function load(path, loader, globalState, oldData, opIdPrefix = 'C') {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.log(\n `ReactGlobalState: useAsyncData data (re-)loading. Path: \"${path || ''}\"`,\n );\n /* eslint-enable no-console */\n }\n const operationId = opIdPrefix + uuid();\n const operationIdPath = path ? `${path}.operationId` : 'operationId';\n globalState.set(operationIdPath, operationId);\n const data = await loader(oldData || globalState.get(path).data);\n const state = globalState.get(path);\n if (operationId === state.operationId) {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupCollapsed(\n `ReactGlobalState: useAsyncData data (re-)loaded. Path: \"${\n path || ''\n }\"`,\n );\n console.log('Data:', cloneDeep(data));\n /* eslint-enable no-console */\n }\n globalState.set(path, {\n ...state,\n data,\n operationId: '',\n timestamp: Date.now(),\n });\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupEnd();\n /* eslint-enable no-console */\n }\n }\n}\n\n/**\n * @typedef {object} AsyncDataEnvelope This type documents the structure of\n * global state segment, created by {@link useAsyncData} hook for storing of\n * loaded async data, and associated metadata.\n * @prop {any} data The actual loaded data.\n * @prop {number} numRefs The count of currently mounted components referencing\n * the data via `useAsyncData` hooks.\n * @prop {string} operationId A unique ID of the current data loading\n * operation, if one is in progress. Changing this ID before the operation\n * completes effectively cancels the ongoing operation, and instructs related\n * hook to ignore the operation result.\n *\n * NOTE: Server-side and client-side operation UIDs start with `S` or `C` letter\n * respectively. At the client side, if an envelop stores `operationId` starting\n * with `S` letter, it is understood as a non-terminated data loading operation\n * during SSR, and it is restarted at the client-side in this case.\n * @prop {number} timestamp Unix timestamp (in milliseconds) of the most\n * recently loaded `data`.\n */\n\n/**\n * @typedef {function} AsyncDataLoader This type documents the signature of\n * async data loader function, expected by {@link useAsyncData} hook.\n * @param {any} oldData Previously loaded data (_i.e._ the data currently stored\n * at the global state `path` managed by the corresponding `useAsyncData` hook,\n * which are assumed to be resolved from a previous call to the loader).\n * The loader does not have to use this argument, it is provided just for\n * convenience.\n * @return {Promise<any>} Async data to store to the state.\n */\n\n/**\n * @category Hooks\n * @func useAsyncData\n * @desc Resolves asynchronous data, and stores them at given `path` of global\n * state. When multiple components rely on asynchronous data at the same `path`,\n * the data are resolved once, and reused until their age is within specified\n * bounds. Once the data are stale, the hook allows to refresh them. It also\n * garbage-collects stale data from the global state when the last component\n * relying on them is unmounted.\n * @param {string} path Dot-delimitered state path, where data envelop is\n * stored.\n * @param {AsyncDataLoader} loader Asynchronous function which resolves (loads)\n * data, which should be stored at the global state `path`. When multiple\n * components\n * use `useAsyncData()` hook for the same `path`, the library assumes that all\n * hook instances are called with the same `loader` (_i.e._ whichever of these\n * loaders is used to resolve async data, the result is acceptable to be reused\n * in all related components).\n * @param {object} [options] Additional options.\n * @param {any[]} [options.deps=[]] An array of dependencies, which trigger\n * data reload when changed. Given dependency changes are watched shallowly\n * (similarly to the standard React's\n * [useEffect()](https://reactjs.org/docs/hooks-reference.html#useeffect)).\n * @param {boolean} [options.noSSR] If `true`, this hook won't load data during\n * server-side rendering.\n * @param {number} [options.garbageCollectAge=maxage] The maximum age of data\n * (in milliseconds), after which they are dropped from the state when the last\n * component referencing them via `useAsyncData()` hook unmounts. Defaults to\n * `maxage` option value.\n * @param {number} [options.maxage=5 x 60 x 1000] The maximum age of\n * data (in milliseconds) acceptable to the hook's caller. If loaded data are\n * older than this value, `null` is returned instead. Defaults to 5 minutes.\n * @param {number} [options.refreshAge=maxage] The maximum age of data\n * (in milliseconds), after which their refreshment will be triggered when\n * any component referencing them via `useAsyncData()` hook (re-)renders.\n * Defaults to `maxage` value.\n * @return {{\n * data: any,\n * loading: boolean,\n * timestamp: number\n * }} Returns an object with three fields: `data` holds the actual result of\n * last `loader` invokation, if any, and if satisfies `maxage` limit; `loading`\n * is a boolean flag, which is `true` if data are being loaded (the hook is\n * waiting for `loader` function resolution); `timestamp` (in milliseconds)\n * is Unix timestamp of related data currently loaded into the global state.\n *\n * Note that loaded data, if any, are stored at the given `path` of global state\n * along with related meta-information, using slightly different state segment\n * structure (see {@link AsyncDataEnvelope}). That segment of the global state\n * can be accessed, and even modified using other hooks,\n * _e.g._ {@link useGlobalState}, but doing so you may interfere with related\n * `useAsyncData()` hooks logic.\n */\nexport default function useAsyncData(\n path,\n loader,\n options = {},\n) {\n let { garbageCollectAge, maxage, refreshAge } = options;\n if (maxage === undefined) maxage = DEFAULT_MAXAGE;\n if (refreshAge === undefined) refreshAge = maxage;\n if (garbageCollectAge === undefined) garbageCollectAge = maxage;\n\n const globalState = getGlobalState();\n const [localState] = useGlobalState(path, {\n data: null,\n numRefs: 0,\n operationId: '',\n timestamp: 0,\n });\n\n if (globalState.ssrContext && !options.noSSR) {\n const state = globalState.get(path);\n if (!state.timestamp && !state.operationId) {\n globalState.ssrContext.pending.push(\n load(path, loader, globalState, state.data, 'S'),\n );\n }\n } else {\n // This takes care about the client-side reference counting, and garbage\n // collection.\n //\n // Note: the Rules of Hook below are violated by conditional call to a hook,\n // but as the condition is actually server-side or client-side environment,\n // it is effectively non-conditional at the runtime.\n //\n // TODO: Though, maybe there is a way to refactor it into a cleaner code.\n // The same applies to other useEffect() hooks below.\n useEffect(() => { // eslint-disable-line react-hooks/rules-of-hooks\n const numRefsPath = path ? `${path}.numRefs` : 'numRefs';\n const numRefs = globalState.get(numRefsPath);\n globalState.set(numRefsPath, numRefs + 1);\n return () => {\n const state = globalState.get(path);\n if (\n state.numRefs === 1\n && garbageCollectAge < Date.now() - state.timestamp\n ) {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.log(\n `ReactGlobalState - useAsyncData garbage collected at path ${\n path || ''\n }`,\n );\n /* eslint-enable no-console */\n }\n globalState.set(path, {\n ...state,\n data: null,\n numRefs: 0,\n timestamp: 0,\n });\n } else globalState.set(numRefsPath, state.numRefs - 1);\n };\n }, [garbageCollectAge, globalState, path]);\n\n // Note: a bunch of Rules of Hooks ignored belows because in our very\n // special case the otherwise wrong behavior is actually what we need.\n\n // Data loading and refreshing.\n let loadTriggered = false;\n useEffect(() => { // eslint-disable-line react-hooks/rules-of-hooks\n const state = globalState.get(path);\n if (refreshAge < Date.now() - state.timestamp\n && (!state.operationId || state.operationId.charAt() === 'S')) {\n load(path, loader, globalState, state.data);\n loadTriggered = true; // eslint-disable-line react-hooks/exhaustive-deps\n }\n });\n\n const deps = options.deps || [];\n useEffect(() => { // eslint-disable-line react-hooks/rules-of-hooks\n if (!loadTriggered && deps.length) load(path, loader, globalState);\n }, deps); // eslint-disable-line react-hooks/exhaustive-deps\n }\n\n return {\n data: maxage < Date.now() - localState.timestamp ? null : localState.data,\n loading: Boolean(localState.operationId),\n timestamp: localState.timestamp,\n };\n}\n"],"file":"useAsyncData.js"}
1
+ {"version":3,"sources":["../../src/useAsyncData.js"],"names":["DEFAULT_MAXAGE","load","path","loader","globalState","oldData","opIdPrefix","process","env","NODE_ENV","console","log","operationId","operationIdPath","set","data","get","state","groupCollapsed","timestamp","Date","now","groupEnd","useAsyncData","options","garbageCollectAge","maxage","refreshAge","undefined","localState","numRefs","ssrContext","noSSR","pending","push","numRefsPath","loadTriggered","charAt","deps","length","loading","Boolean"],"mappings":"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","sourcesContent":["/**\n * Loads and uses async data into the GlobalState path.\n */\n\nimport { cloneDeep } from 'lodash';\nimport { useEffect } from 'react';\nimport { v4 as uuid } from 'uuid';\n\nimport { getGlobalState } from './GlobalStateProvider';\nimport useGlobalState from './useGlobalState';\nimport { isDebugMode } from './utils';\n\nconst DEFAULT_MAXAGE = 5 * 60 * 1000; // 5 minutes.\n\n/**\n * Executes the data loading operation.\n * @param {string} path Data segment path inside the global state.\n * @param {function} loader Data loader.\n * @param {GlobalState} globalState The global state instance.\n * @param {any} [oldData] Optional. Previously fetched data, currently stored in\n * the state, if already fetched by the caller; otherwise, they will be fetched\n * by the load() function itself.\n * @param {string} [opIdPrefix='C'] operationId prefix to use, which should be\n * 'C' at the client-side (default), or 'S' at the server-side (within SSR\n * context).\n * @return {Promise} Resolves once the operation is done.\n * @ignore\n */\nasync function load(path, loader, globalState, oldData, opIdPrefix = 'C') {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.log(\n `ReactGlobalState: useAsyncData data (re-)loading. Path: \"${path || ''}\"`,\n );\n /* eslint-enable no-console */\n }\n const operationId = opIdPrefix + uuid();\n const operationIdPath = path ? `${path}.operationId` : 'operationId';\n globalState.set(operationIdPath, operationId);\n const data = await loader(oldData || globalState.get(path).data);\n const state = globalState.get(path);\n if (operationId === state.operationId) {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupCollapsed(\n `ReactGlobalState: useAsyncData data (re-)loaded. Path: \"${\n path || ''\n }\"`,\n );\n console.log('Data:', cloneDeep(data));\n /* eslint-enable no-console */\n }\n globalState.set(path, {\n ...state,\n data,\n operationId: '',\n timestamp: Date.now(),\n });\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupEnd();\n /* eslint-enable no-console */\n }\n }\n}\n\n/**\n * Resolves asynchronous data, and stores them at given `path` of global\n * state. When multiple components rely on asynchronous data at the same `path`,\n * the data are resolved once, and reused until their age is within specified\n * bounds. Once the data are stale, the hook allows to refresh them. It also\n * garbage-collects stale data from the global state when the last component\n * relying on them is unmounted.\n * @param {string} path Dot-delimitered state path, where data envelop is\n * stored.\n * @param {AsyncDataLoader} loader Asynchronous function which resolves (loads)\n * data, which should be stored at the global state `path`. When multiple\n * components\n * use `useAsyncData()` hook for the same `path`, the library assumes that all\n * hook instances are called with the same `loader` (_i.e._ whichever of these\n * loaders is used to resolve async data, the result is acceptable to be reused\n * in all related components).\n * @param {object} [options] Additional options.\n * @param {any[]} [options.deps=[]] An array of dependencies, which trigger\n * data reload when changed. Given dependency changes are watched shallowly\n * (similarly to the standard React's\n * [useEffect()](https://reactjs.org/docs/hooks-reference.html#useeffect)).\n * @param {boolean} [options.noSSR] If `true`, this hook won't load data during\n * server-side rendering.\n * @param {number} [options.garbageCollectAge=maxage] The maximum age of data\n * (in milliseconds), after which they are dropped from the state when the last\n * component referencing them via `useAsyncData()` hook unmounts. Defaults to\n * `maxage` option value.\n * @param {number} [options.maxage=5 x 60 x 1000] The maximum age of\n * data (in milliseconds) acceptable to the hook's caller. If loaded data are\n * older than this value, `null` is returned instead. Defaults to 5 minutes.\n * @param {number} [options.refreshAge=maxage] The maximum age of data\n * (in milliseconds), after which their refreshment will be triggered when\n * any component referencing them via `useAsyncData()` hook (re-)renders.\n * Defaults to `maxage` value.\n * @return {{\n * data: any,\n * loading: boolean,\n * timestamp: number\n * }} Returns an object with three fields: `data` holds the actual result of\n * last `loader` invokation, if any, and if satisfies `maxage` limit; `loading`\n * is a boolean flag, which is `true` if data are being loaded (the hook is\n * waiting for `loader` function resolution); `timestamp` (in milliseconds)\n * is Unix timestamp of related data currently loaded into the global state.\n *\n * Note that loaded data, if any, are stored at the given `path` of global state\n * along with related meta-information, using slightly different state segment\n * structure (see {@link AsyncDataEnvelope}). That segment of the global state\n * can be accessed, and even modified using other hooks,\n * _e.g._ {@link useGlobalState}, but doing so you may interfere with related\n * `useAsyncData()` hooks logic.\n */\nexport default function useAsyncData(\n path,\n loader,\n options = {},\n) {\n let { garbageCollectAge, maxage, refreshAge } = options;\n if (maxage === undefined) maxage = DEFAULT_MAXAGE;\n if (refreshAge === undefined) refreshAge = maxage;\n if (garbageCollectAge === undefined) garbageCollectAge = maxage;\n\n const globalState = getGlobalState();\n const [localState] = useGlobalState(path, {\n data: null,\n numRefs: 0,\n operationId: '',\n timestamp: 0,\n });\n\n if (globalState.ssrContext && !options.noSSR) {\n const state = globalState.get(path);\n if (!state.timestamp && !state.operationId) {\n globalState.ssrContext.pending.push(\n load(path, loader, globalState, state.data, 'S'),\n );\n }\n } else {\n // This takes care about the client-side reference counting, and garbage\n // collection.\n //\n // Note: the Rules of Hook below are violated by conditional call to a hook,\n // but as the condition is actually server-side or client-side environment,\n // it is effectively non-conditional at the runtime.\n //\n // TODO: Though, maybe there is a way to refactor it into a cleaner code.\n // The same applies to other useEffect() hooks below.\n useEffect(() => { // eslint-disable-line react-hooks/rules-of-hooks\n const numRefsPath = path ? `${path}.numRefs` : 'numRefs';\n const numRefs = globalState.get(numRefsPath);\n globalState.set(numRefsPath, numRefs + 1);\n return () => {\n const state = globalState.get(path);\n if (\n state.numRefs === 1\n && garbageCollectAge < Date.now() - state.timestamp\n ) {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.log(\n `ReactGlobalState - useAsyncData garbage collected at path ${\n path || ''\n }`,\n );\n /* eslint-enable no-console */\n }\n globalState.set(path, {\n ...state,\n data: null,\n numRefs: 0,\n timestamp: 0,\n });\n } else globalState.set(numRefsPath, state.numRefs - 1);\n };\n }, [garbageCollectAge, globalState, path]);\n\n // Note: a bunch of Rules of Hooks ignored belows because in our very\n // special case the otherwise wrong behavior is actually what we need.\n\n // Data loading and refreshing.\n let loadTriggered = false;\n useEffect(() => { // eslint-disable-line react-hooks/rules-of-hooks\n const state = globalState.get(path);\n if (refreshAge < Date.now() - state.timestamp\n && (!state.operationId || state.operationId.charAt() === 'S')) {\n load(path, loader, globalState, state.data);\n loadTriggered = true; // eslint-disable-line react-hooks/exhaustive-deps\n }\n });\n\n const deps = options.deps || [];\n useEffect(() => { // eslint-disable-line react-hooks/rules-of-hooks\n if (!loadTriggered && deps.length) load(path, loader, globalState);\n }, deps); // eslint-disable-line react-hooks/exhaustive-deps\n }\n\n return {\n data: maxage < Date.now() - localState.timestamp ? null : localState.data,\n loading: Boolean(localState.operationId),\n timestamp: localState.timestamp,\n };\n}\n"],"file":"useAsyncData.js"}
@@ -16,9 +16,7 @@ var _utils = require("./utils");
16
16
  // Hook for updates of global state.
17
17
 
18
18
  /**
19
- * @category Hooks
20
- * @func useGlobalState
21
- * @desc The primary hook for interacting with the global state, modeled after
19
+ * The primary hook for interacting with the global state, modeled after
22
20
  * the standard React's
23
21
  * [useState](https://reactjs.org/docs/hooks-reference.html#usestate).
24
22
  * It subscribes a component to a given `path` of global state, and provides
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useGlobalState.js"],"names":["useGlobalState","path","initialValue","globalState","state","get","value","set","localState","setLocalState","callback","active","newState","watch","unWatch","ref","current","setter","newValue","process","env","NODE_ENV","console","groupCollapsed","log","groupEnd"],"mappings":"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","sourcesContent":["// Hook for updates of global state.\n\nimport { cloneDeep, isFunction, isUndefined } from 'lodash';\nimport { useEffect, useRef, useState } from 'react';\n\nimport { getGlobalState } from './GlobalStateProvider';\nimport { isDebugMode } from './utils';\n\n/**\n * @category Hooks\n * @func useGlobalState\n * @desc The primary hook for interacting with the global state, modeled after\n * the standard React's\n * [useState](https://reactjs.org/docs/hooks-reference.html#usestate).\n * It subscribes a component to a given `path` of global state, and provides\n * a function to update it. Each time the value at `path` changes, the hook\n * triggers re-render of its host component.\n *\n * **Note:**\n * - For performance, the library does not copy objects written to / read from\n * global state paths. You MUST NOT manually mutate returned state values,\n * or change objects already written into the global state, without explicitly\n * clonning them first yourself.\n * - State update notifications are asynchronous. When your code does multiple\n * global state updates in the same React rendering cycle, all state update\n * notifications are queued and dispatched together, after the current\n * rendering cycle. In other words, in any given rendering cycle the global\n * state values are \"fixed\", and all changes becomes visible at once in the\n * next triggered rendering pass.\n *\n * @param {string} [path] Dot-delimitered state path. It can be undefined to\n * subscribe for entire state.\n *\n * Under-the-hood state values are read and written using `lodash`\n * [_.get()](https://lodash.com/docs/4.17.15#get) and\n * [_.set()](https://lodash.com/docs/4.17.15#set) methods, thus it is safe\n * to access state paths which have not been created before.\n * @param {any} [initialValue] Initial value to set at the `path`, or its\n * factory:\n * - If a function is given, it will act similar to\n * [the lazy initial state of the standard React's useState()](https://reactjs.org/docs/hooks-reference.html#lazy-initial-state):\n * only if the value at `path` is `undefined`, the function will be executed,\n * and the value it returns will be written to the `path`.\n * - Otherwise, the given value itself will be written to the `path`,\n * if the current value at `path` is `undefined`.\n * @return {Array} It returs an array with two elements: `[value, setValue]`:\n *\n * - The `value` is the current value at given `path`.\n *\n * - The `setValue()` is setter function to write a new value to the `path`.\n *\n * Similar to the standard React's `useState()`, it supports\n * [functional value updates](https://reactjs.org/docs/hooks-reference.html#functional-updates):\n * if `setValue()` is called with a function as argument, that function will\n * be called and its return value will be written to `path`. Otherwise,\n * the argument of `setValue()` itself is written to `path`.\n *\n * Also, similar to the standard React's state setters, `setValue()` is\n * stable function: it does not change between component re-renders.\n */\nexport default function useGlobalState(path, initialValue) {\n const globalState = getGlobalState();\n let state = globalState.get(path);\n if (isUndefined(state) && !isUndefined(initialValue)) {\n const value = isFunction(initialValue) ? initialValue() : initialValue;\n state = globalState.set(path, value);\n }\n const [\n localState,\n setLocalState,\n ] = useState(() => state);\n\n useEffect(() => {\n // Note: the \"callback.active\" flag below is needed to workaround the issue\n // https://github.com/birdofpreyru/react-global-state/issues/33,\n // which, unfortunately, I am not able to reproduce in test environment,\n // but I definitely seen it in the wild.\n const callback = () => {\n if (callback.active) {\n const newState = globalState.get(path);\n if (newState !== localState) setLocalState(() => newState);\n }\n };\n callback.active = true;\n globalState.watch(callback);\n callback();\n return () => {\n delete callback.active;\n globalState.unWatch(callback);\n };\n }, [globalState, localState, path]);\n\n const ref = useRef();\n if (!ref.current) {\n ref.current = {\n localState,\n path,\n setter: (value) => {\n const newValue = isFunction(value)\n ? value(ref.current.localState) : value;\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupCollapsed(\n `ReactGlobalState - useGlobalState setter triggered for path ${\n ref.current.path || ''\n }`,\n );\n console.log('New value:', cloneDeep(newValue));\n console.groupEnd();\n /* eslint-enable no-console */\n }\n\n globalState.set(ref.current.path, newValue);\n\n // The update of local state here is important for managed inputs:\n // if we wait until the global state change notification is delivered\n // (which happens after the next React render), React won't conserve\n // the text cursor inside the currently focused input field (the cursor\n // will jump to the field end, like if the value was changed not by\n // keyboard input).\n setLocalState(() => newValue);\n },\n };\n } else {\n ref.current.localState = localState;\n ref.current.path = path;\n }\n\n return [\n localState,\n ref.current.setter,\n ];\n}\n"],"file":"useGlobalState.js"}
1
+ {"version":3,"sources":["../../src/useGlobalState.js"],"names":["useGlobalState","path","initialValue","globalState","state","get","value","set","localState","setLocalState","callback","active","newState","watch","unWatch","ref","current","setter","newValue","process","env","NODE_ENV","console","groupCollapsed","log","groupEnd"],"mappings":";;;;;;;AAEA;;AACA;;AAEA;;AACA;;AANA;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,SAASA,cAAT,CAAwBC,IAAxB,EAA8BC,YAA9B,EAA4C;AACzD,QAAMC,WAAW,GAAG,0CAApB;AACA,MAAIC,KAAK,GAAGD,WAAW,CAACE,GAAZ,CAAgBJ,IAAhB,CAAZ;;AACA,MAAI,yBAAYG,KAAZ,KAAsB,CAAC,yBAAYF,YAAZ,CAA3B,EAAsD;AACpD,UAAMI,KAAK,GAAG,wBAAWJ,YAAX,IAA2BA,YAAY,EAAvC,GAA4CA,YAA1D;AACAE,IAAAA,KAAK,GAAGD,WAAW,CAACI,GAAZ,CAAgBN,IAAhB,EAAsBK,KAAtB,CAAR;AACD;;AACD,QAAM,CACJE,UADI,EAEJC,aAFI,IAGF,qBAAS,MAAML,KAAf,CAHJ;AAKA,wBAAU,MAAM;AACd;AACA;AACA;AACA;AACA,UAAMM,QAAQ,GAAG,MAAM;AACrB,UAAIA,QAAQ,CAACC,MAAb,EAAqB;AACnB,cAAMC,QAAQ,GAAGT,WAAW,CAACE,GAAZ,CAAgBJ,IAAhB,CAAjB;AACA,YAAIW,QAAQ,KAAKJ,UAAjB,EAA6BC,aAAa,CAAC,MAAMG,QAAP,CAAb;AAC9B;AACF,KALD;;AAMAF,IAAAA,QAAQ,CAACC,MAAT,GAAkB,IAAlB;AACAR,IAAAA,WAAW,CAACU,KAAZ,CAAkBH,QAAlB;AACAA,IAAAA,QAAQ;AACR,WAAO,MAAM;AACX,aAAOA,QAAQ,CAACC,MAAhB;AACAR,MAAAA,WAAW,CAACW,OAAZ,CAAoBJ,QAApB;AACD,KAHD;AAID,GAlBD,EAkBG,CAACP,WAAD,EAAcK,UAAd,EAA0BP,IAA1B,CAlBH;AAoBA,QAAMc,GAAG,GAAG,oBAAZ;;AACA,MAAI,CAACA,GAAG,CAACC,OAAT,EAAkB;AAChBD,IAAAA,GAAG,CAACC,OAAJ,GAAc;AACZR,MAAAA,UADY;AAEZP,MAAAA,IAFY;AAGZgB,MAAAA,MAAM,EAAGX,KAAD,IAAW;AACjB,cAAMY,QAAQ,GAAG,wBAAWZ,KAAX,IACbA,KAAK,CAACS,GAAG,CAACC,OAAJ,CAAYR,UAAb,CADQ,GACmBF,KADpC;;AAEA,YAAIa,OAAO,CAACC,GAAR,CAAYC,QAAZ,KAAyB,YAAzB,IAAyC,yBAA7C,EAA4D;AAC1D;AACAC,UAAAA,OAAO,CAACC,cAAR,CACG,+DACCR,GAAG,CAACC,OAAJ,CAAYf,IAAZ,IAAoB,EACrB,EAHH;AAKAqB,UAAAA,OAAO,CAACE,GAAR,CAAY,YAAZ,EAA0B,uBAAUN,QAAV,CAA1B;AACAI,UAAAA,OAAO,CAACG,QAAR;AACA;AACD;;AAEDtB,QAAAA,WAAW,CAACI,GAAZ,CAAgBQ,GAAG,CAACC,OAAJ,CAAYf,IAA5B,EAAkCiB,QAAlC,EAfiB,CAiBjB;AACA;AACA;AACA;AACA;AACA;;AACAT,QAAAA,aAAa,CAAC,MAAMS,QAAP,CAAb;AACD;AA3BW,KAAd;AA6BD,GA9BD,MA8BO;AACLH,IAAAA,GAAG,CAACC,OAAJ,CAAYR,UAAZ,GAAyBA,UAAzB;AACAO,IAAAA,GAAG,CAACC,OAAJ,CAAYf,IAAZ,GAAmBA,IAAnB;AACD;;AAED,SAAO,CACLO,UADK,EAELO,GAAG,CAACC,OAAJ,CAAYC,MAFP,CAAP;AAID","sourcesContent":["// Hook for updates of global state.\n\nimport { cloneDeep, isFunction, isUndefined } from 'lodash';\nimport { useEffect, useRef, useState } from 'react';\n\nimport { getGlobalState } from './GlobalStateProvider';\nimport { isDebugMode } from './utils';\n\n/**\n * The primary hook for interacting with the global state, modeled after\n * the standard React's\n * [useState](https://reactjs.org/docs/hooks-reference.html#usestate).\n * It subscribes a component to a given `path` of global state, and provides\n * a function to update it. Each time the value at `path` changes, the hook\n * triggers re-render of its host component.\n *\n * **Note:**\n * - For performance, the library does not copy objects written to / read from\n * global state paths. You MUST NOT manually mutate returned state values,\n * or change objects already written into the global state, without explicitly\n * clonning them first yourself.\n * - State update notifications are asynchronous. When your code does multiple\n * global state updates in the same React rendering cycle, all state update\n * notifications are queued and dispatched together, after the current\n * rendering cycle. In other words, in any given rendering cycle the global\n * state values are \"fixed\", and all changes becomes visible at once in the\n * next triggered rendering pass.\n *\n * @param {string} [path] Dot-delimitered state path. It can be undefined to\n * subscribe for entire state.\n *\n * Under-the-hood state values are read and written using `lodash`\n * [_.get()](https://lodash.com/docs/4.17.15#get) and\n * [_.set()](https://lodash.com/docs/4.17.15#set) methods, thus it is safe\n * to access state paths which have not been created before.\n * @param {any} [initialValue] Initial value to set at the `path`, or its\n * factory:\n * - If a function is given, it will act similar to\n * [the lazy initial state of the standard React's useState()](https://reactjs.org/docs/hooks-reference.html#lazy-initial-state):\n * only if the value at `path` is `undefined`, the function will be executed,\n * and the value it returns will be written to the `path`.\n * - Otherwise, the given value itself will be written to the `path`,\n * if the current value at `path` is `undefined`.\n * @return {Array} It returs an array with two elements: `[value, setValue]`:\n *\n * - The `value` is the current value at given `path`.\n *\n * - The `setValue()` is setter function to write a new value to the `path`.\n *\n * Similar to the standard React's `useState()`, it supports\n * [functional value updates](https://reactjs.org/docs/hooks-reference.html#functional-updates):\n * if `setValue()` is called with a function as argument, that function will\n * be called and its return value will be written to `path`. Otherwise,\n * the argument of `setValue()` itself is written to `path`.\n *\n * Also, similar to the standard React's state setters, `setValue()` is\n * stable function: it does not change between component re-renders.\n */\nexport default function useGlobalState(path, initialValue) {\n const globalState = getGlobalState();\n let state = globalState.get(path);\n if (isUndefined(state) && !isUndefined(initialValue)) {\n const value = isFunction(initialValue) ? initialValue() : initialValue;\n state = globalState.set(path, value);\n }\n const [\n localState,\n setLocalState,\n ] = useState(() => state);\n\n useEffect(() => {\n // Note: the \"callback.active\" flag below is needed to workaround the issue\n // https://github.com/birdofpreyru/react-global-state/issues/33,\n // which, unfortunately, I am not able to reproduce in test environment,\n // but I definitely seen it in the wild.\n const callback = () => {\n if (callback.active) {\n const newState = globalState.get(path);\n if (newState !== localState) setLocalState(() => newState);\n }\n };\n callback.active = true;\n globalState.watch(callback);\n callback();\n return () => {\n delete callback.active;\n globalState.unWatch(callback);\n };\n }, [globalState, localState, path]);\n\n const ref = useRef();\n if (!ref.current) {\n ref.current = {\n localState,\n path,\n setter: (value) => {\n const newValue = isFunction(value)\n ? value(ref.current.localState) : value;\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupCollapsed(\n `ReactGlobalState - useGlobalState setter triggered for path ${\n ref.current.path || ''\n }`,\n );\n console.log('New value:', cloneDeep(newValue));\n console.groupEnd();\n /* eslint-enable no-console */\n }\n\n globalState.set(ref.current.path, newValue);\n\n // The update of local state here is important for managed inputs:\n // if we wait until the global state change notification is delivered\n // (which happens after the next React render), React won't conserve\n // the text cursor inside the currently focused input field (the cursor\n // will jump to the field end, like if the value was changed not by\n // keyboard input).\n setLocalState(() => newValue);\n },\n };\n } else {\n ref.current.localState = localState;\n ref.current.path = path;\n }\n\n return [\n localState,\n ref.current.setter,\n ];\n}\n"],"file":"useGlobalState.js"}
@@ -8,18 +8,6 @@ exports.isDebugMode = isDebugMode;
8
8
 
9
9
  // Auxiliary stuff.
10
10
 
11
- /**
12
- * @global
13
- * @const REACT_GLOBAL_STATE_DEBUG
14
- * @desc `REACT_GLOBAL_STATE_DEBUG` is an environment variable you can set
15
- * to any truthy value for Node (or, in case of client-side bundle, inject
16
- * using Webpack's
17
- * [EnvironmentPlugin](https://webpack.js.org/plugins/environment-plugin/))
18
- * to enable debug logging by `react-global-state` library. In either case,
19
- * the logging is enabled in non-production code only, which is tested by
20
- * `process.env.NODE_ENV` value being distinct from `production`.
21
- */
22
-
23
11
  /**
24
12
  * Returns 'true' if debug logging should be performed; 'false' otherwise.
25
13
  *
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils.js"],"names":["isDebugMode","process","env","NODE_ENV","REACT_GLOBAL_STATE_DEBUG","error"],"mappings":";;;;;;;;AAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASA,WAAT,GAAuB;AAC5B,MAAI;AACF,WAAOC,OAAO,CAACC,GAAR,CAAYC,QAAZ,KAAyB,YAAzB,IACF,CAAC,CAACF,OAAO,CAACC,GAAR,CAAYE,wBADnB;AAED,GAHD,CAGE,OAAOC,KAAP,EAAc;AACd,WAAO,KAAP;AACD;AACF;;eAEc,I","sourcesContent":["// Auxiliary stuff.\n\n/**\n * @global\n * @const REACT_GLOBAL_STATE_DEBUG\n * @desc `REACT_GLOBAL_STATE_DEBUG` is an environment variable you can set\n * to any truthy value for Node (or, in case of client-side bundle, inject\n * using Webpack's\n * [EnvironmentPlugin](https://webpack.js.org/plugins/environment-plugin/))\n * to enable debug logging by `react-global-state` library. In either case,\n * the logging is enabled in non-production code only, which is tested by\n * `process.env.NODE_ENV` value being distinct from `production`.\n */\n\n/**\n * Returns 'true' if debug logging should be performed; 'false' otherwise.\n *\n * BEWARE: The actual safeguards for the debug logging still should read\n * if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n * // Some debug logging\n * }\n * to ensure that debug code is stripped out by Webpack in production mode.\n *\n * @returns {boolean}\n * @ignore\n */\nexport function isDebugMode() {\n try {\n return process.env.NODE_ENV !== 'production'\n && !!process.env.REACT_GLOBAL_STATE_DEBUG;\n } catch (error) {\n return false;\n }\n}\n\nexport default null;\n"],"file":"utils.js"}
1
+ {"version":3,"sources":["../../src/utils.js"],"names":["isDebugMode","process","env","NODE_ENV","REACT_GLOBAL_STATE_DEBUG","error"],"mappings":";;;;;;;;AAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASA,WAAT,GAAuB;AAC5B,MAAI;AACF,WAAOC,OAAO,CAACC,GAAR,CAAYC,QAAZ,KAAyB,YAAzB,IACF,CAAC,CAACF,OAAO,CAACC,GAAR,CAAYE,wBADnB;AAED,GAHD,CAGE,OAAOC,KAAP,EAAc;AACd,WAAO,KAAP;AACD;AACF;;eAEc,I","sourcesContent":["// Auxiliary stuff.\n\n/**\n * Returns 'true' if debug logging should be performed; 'false' otherwise.\n *\n * BEWARE: The actual safeguards for the debug logging still should read\n * if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n * // Some debug logging\n * }\n * to ensure that debug code is stripped out by Webpack in production mode.\n *\n * @returns {boolean}\n * @ignore\n */\nexport function isDebugMode() {\n try {\n return process.env.NODE_ENV !== 'production'\n && !!process.env.REACT_GLOBAL_STATE_DEBUG;\n } catch (error) {\n return false;\n }\n}\n\nexport default null;\n"],"file":"utils.js"}
@@ -19,9 +19,9 @@ var _lodash = require("lodash");
19
19
 
20
20
  var _utils = require("./utils");
21
21
 
22
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
22
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
23
23
 
24
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
24
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
25
25
 
26
26
  var ERR_NO_SSR_WATCH = 'GlobalState must not be watched at server side';
27
27
  /**
@@ -37,9 +37,7 @@ function fullPath(statePath) {
37
37
 
38
38
  var GlobalState = /*#__PURE__*/function () {
39
39
  /**
40
- * @class GlobalState
41
- * @classdesc Represents global state objects.
42
- * @desc Creates a new global state object.
40
+ * Creates a new global state object.
43
41
  * @param {any} [initialState] Intial global state content.
44
42
  * @param {SsrContext} [ssrContext] Server-side rendering context.
45
43
  */
@@ -71,9 +69,7 @@ var GlobalState = /*#__PURE__*/function () {
71
69
 
72
70
  }
73
71
  /**
74
- * @instance
75
- * @memberof GlobalState
76
- * @desc Gets the value at given `path` of global state. If `path` is null or
72
+ * Gets the value at given `path` of global state. If `path` is null or
77
73
  * undefined, the entire state object is returned.
78
74
  * @param {string} [path] Dot-delimitered state path. If not given, entire
79
75
  * global state content is returned.
@@ -87,9 +83,7 @@ var GlobalState = /*#__PURE__*/function () {
87
83
  return (0, _lodash.get)(this, fullPath(path));
88
84
  }
89
85
  /**
90
- * @instance
91
- * @memberof GlobalState
92
- * @desc Writes the `value` to given global state `path`.
86
+ * Writes the `value` to given global state `path`.
93
87
  * @param {string} [path] Dot-delimitered state path. If not given, entire
94
88
  * global state content is replaced by the `value`.
95
89
  * @param {any} value The value.
@@ -151,9 +145,7 @@ var GlobalState = /*#__PURE__*/function () {
151
145
  return value;
152
146
  }
153
147
  /**
154
- * @instance
155
- * @memberof GlobalState
156
- * @desc Unsubscribes `callback` from watching state updates; no operation if
148
+ * Unsubscribes `callback` from watching state updates; no operation if
157
149
  * `callback` is not subscribed to the state updates.
158
150
  * @param {function} callback
159
151
  * @throws if {@link SsrContext} is attached to the state instance: the state
@@ -173,9 +165,7 @@ var GlobalState = /*#__PURE__*/function () {
173
165
  }
174
166
  }
175
167
  /**
176
- * @instance
177
- * @memberof GlobalState
178
- * @desc Subscribes `callback` to watch state updates; no operation if
168
+ * Subscribes `callback` to watch state updates; no operation if
179
169
  * `callback` is already subscribed to this state instance.
180
170
  * @param {function} callback It will be called without any arguments every
181
171
  * time the state content changes (note, howhever, separate state updates can
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/GlobalState.js"],"names":["ERR_NO_SSR_WATCH","fullPath","statePath","GlobalState","initialState","ssrContext","state","nextNotifierId","watchers","dirty","pending","process","env","NODE_ENV","msg","console","groupCollapsed","log","groupEnd","path","value","p","pos","pathSegments","i","length","seg","next","setTimeout","forEach","w","callback","Error","indexOf","pop","push"],"mappings":";;;;;;;;;;;;;;;;;AAAA;;AAUA;;;;;;AAEA,IAAMA,gBAAgB,GAAG,gDAAzB;AAEA;AACA;AACA;AACA;AACA;AACA;;AACA,SAASC,QAAT,CAAkBC,SAAlB,EAA6B;AAC3B,SAAO,mBAAMA,SAAN,IAAmB,OAAnB,mBAAsCA,SAAtC,CAAP;AACD;;IAEoBC,W;AACnB;AACF;AACA;AACA;AACA;AACA;AACA;AACE,uBAAYC,YAAZ,EAA0BC,UAA1B,EAAsC;AAAA;;AACpC;AACA,SAAKC,KAAL,GAAa,uBAAUF,YAAV,CAAb;AACA,SAAKG,cAAL,GAAsB,IAAtB;AACA,SAAKC,QAAL,GAAgB,EAAhB;;AAEA,QAAIH,UAAJ,EAAgB;AACdA,MAAAA,UAAU,CAACI,KAAX,GAAmB,KAAnB;AACAJ,MAAAA,UAAU,CAACK,OAAX,GAAqB,EAArB;AACAL,MAAAA,UAAU,CAACC,KAAX,GAAmB,KAAKA,KAAxB;AACA,WAAKD,UAAL,GAAkBA,UAAlB;AACD;;AAED,QAAIM,OAAO,CAACC,GAAR,CAAYC,QAAZ,KAAyB,YAAzB,IAAyC,yBAA7C,EAA4D;AAC1D;AACA,UAAIC,GAAG,GAAG,8BAAV;AACA,UAAIT,UAAJ,EAAgBS,GAAG,IAAI,aAAP;AAChBC,MAAAA,OAAO,CAACC,cAAR,CAAuBF,GAAvB;AACAC,MAAAA,OAAO,CAACE,GAAR,CAAY,gBAAZ,EAA8B,uBAAUb,YAAV,CAA9B;AACAW,MAAAA,OAAO,CAACG,QAAR;AACA;AACD;AACD;;AACD;AAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;WACE,aAAIC,IAAJ,EAAU;AACR,aAAO,iBAAI,IAAJ,EAAUlB,QAAQ,CAACkB,IAAD,CAAlB,CAAP;AACD;AAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;WACE,aAAIA,IAAJ,EAAUC,KAAV,EAAiB;AAAA;;AACf,UAAMC,CAAC,GAAGpB,QAAQ,CAACkB,IAAD,CAAlB;;AACA,UAAIC,KAAK,KAAK,iBAAI,IAAJ,EAAUC,CAAV,CAAd,EAA4B;AAC1B,YAAIV,OAAO,CAACC,GAAR,CAAYC,QAAZ,KAAyB,YAAzB,IAAyC,yBAA7C,EAA4D;AAC1D;AACAE,UAAAA,OAAO,CAACC,cAAR,4CACqCG,IAAI,IAAI,EAD7C;AAGAJ,UAAAA,OAAO,CAACE,GAAR,CAAY,YAAZ,EAA0B,uBAAUG,KAAV,CAA1B;AACA;AACD;;AACD,YAAIE,GAAG,GAAG,IAAV;AACA,YAAMC,YAAY,GAAG,oBAAOF,CAAP,CAArB;;AACA,aAAK,IAAIG,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAGD,YAAY,CAACE,MAAb,GAAsB,CAA1C,EAA6CD,CAAC,IAAI,CAAlD,EAAqD;AACnD,cAAME,GAAG,GAAGH,YAAY,CAACC,CAAD,CAAxB;AACA,cAAMG,IAAI,GAAGL,GAAG,CAACI,GAAD,CAAhB;AACA,cAAI,qBAAQC,IAAR,CAAJ,EAAmBL,GAAG,CAACI,GAAD,CAAH,oCAAeC,IAAf,EAAnB,KACK,IAAI,sBAASA,IAAT,CAAJ,EAAoBL,GAAG,CAACI,GAAD,CAAH,qBAAgBC,IAAhB,EAApB,KACA;AACLL,UAAAA,GAAG,GAAGA,GAAG,CAACI,GAAD,CAAT;AACD,SAlByB,CAoB1B;AACA;AACA;AACA;AACA;;;AACA,yBAAI,IAAJ,EAAUL,CAAV,EAAaD,KAAb;;AAEA,YAAI,KAAKf,UAAT,EAAqB;AACnB,eAAKA,UAAL,CAAgBI,KAAhB,GAAwB,IAAxB;AACA,eAAKJ,UAAL,CAAgBC,KAAhB,GAAwB,KAAKA,KAA7B;AACD,SAHD,MAGO,IAAI,CAAC,KAAKC,cAAV,EAA0B;AAC/B,eAAKA,cAAL,GAAsBqB,UAAU,CAAC,YAAM;AACrC,YAAA,KAAI,CAACrB,cAAL,GAAsB,IAAtB;AACA,6CAAI,KAAI,CAACC,QAAT,EAAmBqB,OAAnB,CAA2B,UAACC,CAAD;AAAA,qBAAOA,CAAC,EAAR;AAAA,aAA3B;AACD,WAH+B,CAAhC;AAID;;AACD,YAAInB,OAAO,CAACC,GAAR,CAAYC,QAAZ,KAAyB,YAAzB,IAAyC,yBAA7C,EAA4D;AAC1D;AACAE,UAAAA,OAAO,CAACE,GAAR,CAAY,YAAZ,EAA0B,uBAAU,KAAKX,KAAf,CAA1B;AACAS,UAAAA,OAAO,CAACG,QAAR;AACA;AACD;AACF;;AACD,aAAOE,KAAP;AACD;AAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;WACE,iBAAQW,QAAR,EAAkB;AAChB,UAAI,KAAK1B,UAAT,EAAqB,MAAM,IAAI2B,KAAJ,CAAUhC,gBAAV,CAAN;AACrB,UAAQQ,QAAR,GAAqB,IAArB,CAAQA,QAAR;AACA,UAAMc,GAAG,GAAGd,QAAQ,CAACyB,OAAT,CAAiBF,QAAjB,CAAZ;;AACA,UAAIT,GAAG,IAAI,CAAX,EAAc;AACZd,QAAAA,QAAQ,CAACc,GAAD,CAAR,GAAgBd,QAAQ,CAACA,QAAQ,CAACiB,MAAT,GAAkB,CAAnB,CAAxB;AACAjB,QAAAA,QAAQ,CAAC0B,GAAT;AACD;AACF;AAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;WACE,eAAMH,QAAN,EAAgB;AACd,UAAI,KAAK1B,UAAT,EAAqB,MAAM,IAAI2B,KAAJ,CAAUhC,gBAAV,CAAN;AACrB,UAAQQ,QAAR,GAAqB,IAArB,CAAQA,QAAR;;AACA,UAAIA,QAAQ,CAACyB,OAAT,CAAiBF,QAAjB,IAA6B,CAAjC,EAAoC;AAClCvB,QAAAA,QAAQ,CAAC2B,IAAT,CAAcJ,QAAd;AACD;AACF","sourcesContent":["import {\n cloneDeep,\n get,\n isArray,\n isObject,\n isNil,\n set,\n toPath,\n} from 'lodash';\n\nimport { isDebugMode } from './utils';\n\nconst ERR_NO_SSR_WATCH = 'GlobalState must not be watched at server side';\n\n/**\n * Transform state path into the full path inside GlobalState object.\n * @param {string} statePath\n * @return {string}\n * @ignore\n */\nfunction fullPath(statePath) {\n return isNil(statePath) ? 'state' : `state.${statePath}`;\n}\n\nexport default class GlobalState {\n /**\n * @class GlobalState\n * @classdesc Represents global state objects.\n * @desc Creates a new global state object.\n * @param {any} [initialState] Intial global state content.\n * @param {SsrContext} [ssrContext] Server-side rendering context.\n */\n constructor(initialState, ssrContext) {\n /* eslint-disable no-param-reassign */\n this.state = cloneDeep(initialState);\n this.nextNotifierId = null;\n this.watchers = [];\n\n if (ssrContext) {\n ssrContext.dirty = false;\n ssrContext.pending = [];\n ssrContext.state = this.state;\n this.ssrContext = ssrContext;\n }\n\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n let msg = 'New ReactGlobalState created';\n if (ssrContext) msg += ' (SSR mode)';\n console.groupCollapsed(msg);\n console.log('Initial state:', cloneDeep(initialState));\n console.groupEnd();\n /* eslint-enable no-console */\n }\n /* eslint-enable no-param-reassign */\n }\n\n /**\n * @instance\n * @memberof GlobalState\n * @desc Gets the value at given `path` of global state. If `path` is null or\n * undefined, the entire state object is returned.\n * @param {string} [path] Dot-delimitered state path. If not given, entire\n * global state content is returned.\n * @return {any}\n */\n get(path) {\n return get(this, fullPath(path));\n }\n\n /**\n * @instance\n * @memberof GlobalState\n * @desc Writes the `value` to given global state `path`.\n * @param {string} [path] Dot-delimitered state path. If not given, entire\n * global state content is replaced by the `value`.\n * @param {any} value The value.\n * @return {any} Given `value` itself.\n */\n set(path, value) {\n const p = fullPath(path);\n if (value !== get(this, p)) {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupCollapsed(\n `ReactGlobalState update. Path: \"${path || ''}\"`,\n );\n console.log('New value:', cloneDeep(value));\n /* eslint-enable no-console */\n }\n let pos = this;\n const pathSegments = toPath(p);\n for (let i = 0; i < pathSegments.length - 1; i += 1) {\n const seg = pathSegments[i];\n const next = pos[seg];\n if (isArray(next)) pos[seg] = [...next];\n else if (isObject(next)) pos[seg] = { ...next };\n else break;\n pos = pos[seg];\n }\n\n // TODO: With such naive use of _.set, the state is mutated in place,\n // which may cause tons of unexpected side effects for dependants.\n // It will be better to partially clone the state, so that any existing\n // references are not mutated, while the full deep clonning is also\n // avoided.\n set(this, p, value);\n\n if (this.ssrContext) {\n this.ssrContext.dirty = true;\n this.ssrContext.state = this.state;\n } else if (!this.nextNotifierId) {\n this.nextNotifierId = setTimeout(() => {\n this.nextNotifierId = null;\n [...this.watchers].forEach((w) => w());\n });\n }\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.log('New state:', cloneDeep(this.state));\n console.groupEnd();\n /* eslint-enable no-console */\n }\n }\n return value;\n }\n\n /**\n * @instance\n * @memberof GlobalState\n * @desc Unsubscribes `callback` from watching state updates; no operation if\n * `callback` is not subscribed to the state updates.\n * @param {function} callback\n * @throws if {@link SsrContext} is attached to the state instance: the state\n * watching functionality is intended for client-side (non-SSR) only.\n */\n unWatch(callback) {\n if (this.ssrContext) throw new Error(ERR_NO_SSR_WATCH);\n const { watchers } = this;\n const pos = watchers.indexOf(callback);\n if (pos >= 0) {\n watchers[pos] = watchers[watchers.length - 1];\n watchers.pop();\n }\n }\n\n /**\n * @instance\n * @memberof GlobalState\n * @desc Subscribes `callback` to watch state updates; no operation if\n * `callback` is already subscribed to this state instance.\n * @param {function} callback It will be called without any arguments every\n * time the state content changes (note, howhever, separate state updates can\n * be applied to the state at once, and watching callbacks will be called once\n * after such bulk update).\n * @throws if {@link SsrContext} is attached to the state instance: the state\n * watching functionality is intended for client-side (non-SSR) only.\n */\n watch(callback) {\n if (this.ssrContext) throw new Error(ERR_NO_SSR_WATCH);\n const { watchers } = this;\n if (watchers.indexOf(callback) < 0) {\n watchers.push(callback);\n }\n }\n}\n"],"file":"GlobalState.js"}
1
+ {"version":3,"sources":["../../src/GlobalState.js"],"names":["ERR_NO_SSR_WATCH","fullPath","statePath","GlobalState","initialState","ssrContext","state","nextNotifierId","watchers","dirty","pending","process","env","NODE_ENV","msg","console","groupCollapsed","log","groupEnd","path","value","p","pos","pathSegments","i","length","seg","next","setTimeout","forEach","w","callback","Error","indexOf","pop","push"],"mappings":"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","sourcesContent":["import {\n cloneDeep,\n get,\n isArray,\n isObject,\n isNil,\n set,\n toPath,\n} from 'lodash';\n\nimport { isDebugMode } from './utils';\n\nconst ERR_NO_SSR_WATCH = 'GlobalState must not be watched at server side';\n\n/**\n * Transform state path into the full path inside GlobalState object.\n * @param {string} statePath\n * @return {string}\n * @ignore\n */\nfunction fullPath(statePath) {\n return isNil(statePath) ? 'state' : `state.${statePath}`;\n}\n\nexport default class GlobalState {\n /**\n * Creates a new global state object.\n * @param {any} [initialState] Intial global state content.\n * @param {SsrContext} [ssrContext] Server-side rendering context.\n */\n constructor(initialState, ssrContext) {\n /* eslint-disable no-param-reassign */\n this.state = cloneDeep(initialState);\n this.nextNotifierId = null;\n this.watchers = [];\n\n if (ssrContext) {\n ssrContext.dirty = false;\n ssrContext.pending = [];\n ssrContext.state = this.state;\n this.ssrContext = ssrContext;\n }\n\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n let msg = 'New ReactGlobalState created';\n if (ssrContext) msg += ' (SSR mode)';\n console.groupCollapsed(msg);\n console.log('Initial state:', cloneDeep(initialState));\n console.groupEnd();\n /* eslint-enable no-console */\n }\n /* eslint-enable no-param-reassign */\n }\n\n /**\n * Gets the value at given `path` of global state. If `path` is null or\n * undefined, the entire state object is returned.\n * @param {string} [path] Dot-delimitered state path. If not given, entire\n * global state content is returned.\n * @return {any}\n */\n get(path) {\n return get(this, fullPath(path));\n }\n\n /**\n * Writes the `value` to given global state `path`.\n * @param {string} [path] Dot-delimitered state path. If not given, entire\n * global state content is replaced by the `value`.\n * @param {any} value The value.\n * @return {any} Given `value` itself.\n */\n set(path, value) {\n const p = fullPath(path);\n if (value !== get(this, p)) {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupCollapsed(\n `ReactGlobalState update. Path: \"${path || ''}\"`,\n );\n console.log('New value:', cloneDeep(value));\n /* eslint-enable no-console */\n }\n let pos = this;\n const pathSegments = toPath(p);\n for (let i = 0; i < pathSegments.length - 1; i += 1) {\n const seg = pathSegments[i];\n const next = pos[seg];\n if (isArray(next)) pos[seg] = [...next];\n else if (isObject(next)) pos[seg] = { ...next };\n else break;\n pos = pos[seg];\n }\n\n // TODO: With such naive use of _.set, the state is mutated in place,\n // which may cause tons of unexpected side effects for dependants.\n // It will be better to partially clone the state, so that any existing\n // references are not mutated, while the full deep clonning is also\n // avoided.\n set(this, p, value);\n\n if (this.ssrContext) {\n this.ssrContext.dirty = true;\n this.ssrContext.state = this.state;\n } else if (!this.nextNotifierId) {\n this.nextNotifierId = setTimeout(() => {\n this.nextNotifierId = null;\n [...this.watchers].forEach((w) => w());\n });\n }\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.log('New state:', cloneDeep(this.state));\n console.groupEnd();\n /* eslint-enable no-console */\n }\n }\n return value;\n }\n\n /**\n * Unsubscribes `callback` from watching state updates; no operation if\n * `callback` is not subscribed to the state updates.\n * @param {function} callback\n * @throws if {@link SsrContext} is attached to the state instance: the state\n * watching functionality is intended for client-side (non-SSR) only.\n */\n unWatch(callback) {\n if (this.ssrContext) throw new Error(ERR_NO_SSR_WATCH);\n const { watchers } = this;\n const pos = watchers.indexOf(callback);\n if (pos >= 0) {\n watchers[pos] = watchers[watchers.length - 1];\n watchers.pop();\n }\n }\n\n /**\n * Subscribes `callback` to watch state updates; no operation if\n * `callback` is already subscribed to this state instance.\n * @param {function} callback It will be called without any arguments every\n * time the state content changes (note, howhever, separate state updates can\n * be applied to the state at once, and watching callbacks will be called once\n * after such bulk update).\n * @throws if {@link SsrContext} is attached to the state instance: the state\n * watching functionality is intended for client-side (non-SSR) only.\n */\n watch(callback) {\n if (this.ssrContext) throw new Error(ERR_NO_SSR_WATCH);\n const { watchers } = this;\n if (watchers.indexOf(callback) < 0) {\n watchers.push(callback);\n }\n }\n}\n"],"file":"GlobalState.js"}
@@ -18,27 +18,9 @@ var _GlobalState = _interopRequireDefault(require("./GlobalState"));
18
18
  var _jsxRuntime = require("react/jsx-runtime");
19
19
 
20
20
  /* eslint-disable react/prop-types */
21
-
22
- /**
23
- * @typedef {object} SsrContext Holds global-state-related information,
24
- * which should be persistent across rendering iterations during server-side
25
- * rendering (SSR). For the first SSR iteration any object, including an empty
26
- * `{}`, may be provided to {@link &lt;GlobalStateProvider&gt;}: in either case
27
- * all its fields listed below will be (re-)initialized as needed, and any other
28
- * fields contained in the object won't be touched by the library (thus, you may
29
- * use it to keep other data you need across SSR iterations, and you can access
30
- * it from React components via {@link getSsrContext} hook).
31
- * @prop {boolean} dirty `true` if the global state has been modified in
32
- * the last SSR iteration; `false` otherwise.
33
- * @prop {Promise[]} pending An array of promises waiting for completion of
34
- * asynchronous state operations (like {@link useAsyncData}), initiated during
35
- * the last SSR iteration.
36
- * @prop {any} state The global state content at the end of last SSR iteration.
37
- */
38
21
  var context = /*#__PURE__*/(0, _react.createContext)();
39
22
  /**
40
- * @category Hooks
41
- * @desc Gets {@link GlobalState} instance from the context. In most cases
23
+ * Gets {@link GlobalState} instance from the context. In most cases
42
24
  * you should use {@link useGlobalState}, and other hooks to interact with
43
25
  * the global state, instead of accessing it directly.
44
26
  * @return {GlobalState}
@@ -87,9 +69,7 @@ function getSsrContext() {
87
69
  return ssrContext;
88
70
  }
89
71
  /**
90
- * @category Components
91
- * @name &lt;GlobalStateProvider&gt;
92
- * @desc Provides global state to its children.
72
+ * Provides global state to its children.
93
73
  * @prop {ReactNode} [children] Component children, which will be provided with
94
74
  * the global state, and rendered in place of the provider.
95
75
  * @prop {any} [initialState] Initial content of the global state.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/GlobalStateProvider.jsx"],"names":["context","getGlobalState","globalState","Error","getSsrContext","throwWithoutSsrContext","ssrContext","GlobalStateProvider","children","initialState","stateProxy","state","GlobalState"],"mappings":";;;;;;;;;;;;;AAmBA;;AAEA;;;;AArBA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA,IAAMA,OAAO,gBAAG,2BAAhB;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AACO,SAASC,cAAT,GAA0B;AAC/B;AACA;AACA;AACA;AACA;;AACA;AACA,MAAMC,WAAW,GAAG,uBAAWF,OAAX,CAApB;AACA;;AACA,MAAI,CAACE,WAAL,EAAkB,MAAM,IAAIC,KAAJ,CAAU,6BAAV,CAAN;AAClB,SAAOD,WAAP;AACD;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACO,SAASE,aAAT,GAAsD;AAAA,MAA/BC,sBAA+B,uEAAN,IAAM;;AAC3D,wBAAuBJ,cAAc,EAArC;AAAA,MAAQK,UAAR,mBAAQA,UAAR;;AACA,MAAI,CAACA,UAAD,IAAeD,sBAAnB,EAA2C;AACzC,UAAM,IAAIF,KAAJ,CAAU,sBAAV,CAAN;AACD;;AACD,SAAOG,UAAP;AACD;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACe,SAASC,mBAAT,OAKZ;AAAA,MAJDC,QAIC,QAJDA,QAIC;AAAA,MAHDC,YAGC,QAHDA,YAGC;AAAA,MAFDH,UAEC,QAFDA,UAEC;AAAA,MADDI,UACC,QADDA,UACC;AACD,MAAIC,KAAJ,CADC,CAED;AACA;AACA;AACA;;AACA;;AACA,MAAID,UAAU,YAAYE,oBAA1B,EAAuCD,KAAK,GAAGD,UAAR,CAAvC,KACK,IAAIA,UAAJ,EAAgBC,KAAK,GAAGV,cAAc,EAAtB,CAAhB;AAAA,oBACU,qBAAS,IAAIW,oBAAJ,CAAgBH,YAAhB,EAA8BH,UAA9B,CAAT,CADV;;AAAA;;AACCK,IAAAA,KADD;AAAA;AAEL;;AACA,sBACE,qBAAC,OAAD,CAAS,QAAT;AAAkB,IAAA,KAAK,EAAEA,KAAzB;AAAA,cACGH;AADH,IADF;AAKD","sourcesContent":["/* eslint-disable react/prop-types */\n\n/**\n * @typedef {object} SsrContext Holds global-state-related information,\n * which should be persistent across rendering iterations during server-side\n * rendering (SSR). For the first SSR iteration any object, including an empty\n * `{}`, may be provided to {@link &lt;GlobalStateProvider&gt;}: in either case\n * all its fields listed below will be (re-)initialized as needed, and any other\n * fields contained in the object won't be touched by the library (thus, you may\n * use it to keep other data you need across SSR iterations, and you can access\n * it from React components via {@link getSsrContext} hook).\n * @prop {boolean} dirty `true` if the global state has been modified in\n * the last SSR iteration; `false` otherwise.\n * @prop {Promise[]} pending An array of promises waiting for completion of\n * asynchronous state operations (like {@link useAsyncData}), initiated during\n * the last SSR iteration.\n * @prop {any} state The global state content at the end of last SSR iteration.\n */\n\nimport { createContext, useContext, useState } from 'react';\n\nimport GlobalState from './GlobalState';\n\nconst context = createContext();\n\n/**\n * @category Hooks\n * @desc Gets {@link GlobalState} instance from the context. In most cases\n * you should use {@link useGlobalState}, and other hooks to interact with\n * the global state, instead of accessing it directly.\n * @return {GlobalState}\n */\nexport function getGlobalState() {\n // Here Rules of Hooks are violated because \"getGlobalState()\" does not follow\n // convention that hook names should start with use... This is intentional in\n // our case, as getGlobalState() hook is intended for advance scenarious,\n // while the normal interaction with the global state should happen via\n // another hook, useGlobalState().\n /* eslint-disable react-hooks/rules-of-hooks */\n const globalState = useContext(context);\n /* eslint-enable react-hooks/rules-of-hooks */\n if (!globalState) throw new Error('Missing GlobalStateProvider');\n return globalState;\n}\n\n/**\n * @category Hooks\n * @desc Gets SSR context.\n * @param {boolean} [throwWithoutSsrContext=true] If `true` (default),\n * this hook will throw if no SSR context is attached to the global state;\n * set `false` to not throw in such case. In either case the hook will throw\n * if the {@link &lt;GlobalStateProvider&gt;} (hence the state) is missing.\n * @returns {SsrContext} SSR context.\n * @throws\n * - If current component has no parent {@link &lt;GlobalStateProvider&gt;}\n * in the rendered React tree.\n * - If `throwWithoutSsrContext` is `true`, and there is no SSR context attached\n * to the global state provided by {@link &lt;GlobalStateProvider&gt;}.\n */\nexport function getSsrContext(throwWithoutSsrContext = true) {\n const { ssrContext } = getGlobalState();\n if (!ssrContext && throwWithoutSsrContext) {\n throw new Error('No SSR context found');\n }\n return ssrContext;\n}\n\n/**\n * @category Components\n * @name &lt;GlobalStateProvider&gt;\n * @desc Provides global state to its children.\n * @prop {ReactNode} [children] Component children, which will be provided with\n * the global state, and rendered in place of the provider.\n * @prop {any} [initialState] Initial content of the global state.\n * @prop {SsrContext} [ssrContext] Server-side rendering (SSR) context.\n * @prop {boolean|GlobalState} [stateProxy] This option is useful for code\n * splitting and SSR implementation:\n * - If `true`, this provider instance will fetch and reuse the global state\n * from a parent provider.\n * - If `GlobalState` instance, it will be used by this provider.\n * - If not given, a new `GlobalState` instance will be created and used.\n */\nexport default function GlobalStateProvider({\n children,\n initialState,\n ssrContext,\n stateProxy,\n}) {\n let state;\n // Here Rules of Hooks are violated because hooks are called conditionally,\n // however we assume that these properties should not change at runtime, thus\n // the actual hook order is preserved. Probably, it should be handled better,\n // though.\n /* eslint-disable react-hooks/rules-of-hooks */\n if (stateProxy instanceof GlobalState) state = stateProxy;\n else if (stateProxy) state = getGlobalState();\n else [state] = useState(new GlobalState(initialState, ssrContext));\n /* eslint-enable react-hooks/rules-of-hooks */\n return (\n <context.Provider value={state}>\n {children}\n </context.Provider>\n );\n}\n"],"file":"GlobalStateProvider.js"}
1
+ {"version":3,"sources":["../../src/GlobalStateProvider.jsx"],"names":["context","getGlobalState","globalState","Error","getSsrContext","throwWithoutSsrContext","ssrContext","GlobalStateProvider","children","initialState","stateProxy","state","GlobalState"],"mappings":";;;;;;;;;;;;;AAEA;;AAEA;;;;AAJA;AAMA,IAAMA,OAAO,gBAAG,2BAAhB;AAEA;AACA;AACA;AACA;AACA;AACA;;AACO,SAASC,cAAT,GAA0B;AAC/B;AACA;AACA;AACA;AACA;;AACA;AACA,MAAMC,WAAW,GAAG,uBAAWF,OAAX,CAApB;AACA;;AACA,MAAI,CAACE,WAAL,EAAkB,MAAM,IAAIC,KAAJ,CAAU,6BAAV,CAAN;AAClB,SAAOD,WAAP;AACD;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACO,SAASE,aAAT,GAAsD;AAAA,MAA/BC,sBAA+B,uEAAN,IAAM;;AAC3D,wBAAuBJ,cAAc,EAArC;AAAA,MAAQK,UAAR,mBAAQA,UAAR;;AACA,MAAI,CAACA,UAAD,IAAeD,sBAAnB,EAA2C;AACzC,UAAM,IAAIF,KAAJ,CAAU,sBAAV,CAAN;AACD;;AACD,SAAOG,UAAP;AACD;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACe,SAASC,mBAAT,OAKZ;AAAA,MAJDC,QAIC,QAJDA,QAIC;AAAA,MAHDC,YAGC,QAHDA,YAGC;AAAA,MAFDH,UAEC,QAFDA,UAEC;AAAA,MADDI,UACC,QADDA,UACC;AACD,MAAIC,KAAJ,CADC,CAED;AACA;AACA;AACA;;AACA;;AACA,MAAID,UAAU,YAAYE,oBAA1B,EAAuCD,KAAK,GAAGD,UAAR,CAAvC,KACK,IAAIA,UAAJ,EAAgBC,KAAK,GAAGV,cAAc,EAAtB,CAAhB;AAAA,oBACU,qBAAS,IAAIW,oBAAJ,CAAgBH,YAAhB,EAA8BH,UAA9B,CAAT,CADV;;AAAA;;AACCK,IAAAA,KADD;AAAA;AAEL;;AACA,sBACE,qBAAC,OAAD,CAAS,QAAT;AAAkB,IAAA,KAAK,EAAEA,KAAzB;AAAA,cACGH;AADH,IADF;AAKD","sourcesContent":["/* eslint-disable react/prop-types */\n\nimport { createContext, useContext, useState } from 'react';\n\nimport GlobalState from './GlobalState';\n\nconst context = createContext();\n\n/**\n * Gets {@link GlobalState} instance from the context. In most cases\n * you should use {@link useGlobalState}, and other hooks to interact with\n * the global state, instead of accessing it directly.\n * @return {GlobalState}\n */\nexport function getGlobalState() {\n // Here Rules of Hooks are violated because \"getGlobalState()\" does not follow\n // convention that hook names should start with use... This is intentional in\n // our case, as getGlobalState() hook is intended for advance scenarious,\n // while the normal interaction with the global state should happen via\n // another hook, useGlobalState().\n /* eslint-disable react-hooks/rules-of-hooks */\n const globalState = useContext(context);\n /* eslint-enable react-hooks/rules-of-hooks */\n if (!globalState) throw new Error('Missing GlobalStateProvider');\n return globalState;\n}\n\n/**\n * @category Hooks\n * @desc Gets SSR context.\n * @param {boolean} [throwWithoutSsrContext=true] If `true` (default),\n * this hook will throw if no SSR context is attached to the global state;\n * set `false` to not throw in such case. In either case the hook will throw\n * if the {@link &lt;GlobalStateProvider&gt;} (hence the state) is missing.\n * @returns {SsrContext} SSR context.\n * @throws\n * - If current component has no parent {@link &lt;GlobalStateProvider&gt;}\n * in the rendered React tree.\n * - If `throwWithoutSsrContext` is `true`, and there is no SSR context attached\n * to the global state provided by {@link &lt;GlobalStateProvider&gt;}.\n */\nexport function getSsrContext(throwWithoutSsrContext = true) {\n const { ssrContext } = getGlobalState();\n if (!ssrContext && throwWithoutSsrContext) {\n throw new Error('No SSR context found');\n }\n return ssrContext;\n}\n\n/**\n * Provides global state to its children.\n * @prop {ReactNode} [children] Component children, which will be provided with\n * the global state, and rendered in place of the provider.\n * @prop {any} [initialState] Initial content of the global state.\n * @prop {SsrContext} [ssrContext] Server-side rendering (SSR) context.\n * @prop {boolean|GlobalState} [stateProxy] This option is useful for code\n * splitting and SSR implementation:\n * - If `true`, this provider instance will fetch and reuse the global state\n * from a parent provider.\n * - If `GlobalState` instance, it will be used by this provider.\n * - If not given, a new `GlobalState` instance will be created and used.\n */\nexport default function GlobalStateProvider({\n children,\n initialState,\n ssrContext,\n stateProxy,\n}) {\n let state;\n // Here Rules of Hooks are violated because hooks are called conditionally,\n // however we assume that these properties should not change at runtime, thus\n // the actual hook order is preserved. Probably, it should be handled better,\n // though.\n /* eslint-disable react-hooks/rules-of-hooks */\n if (stateProxy instanceof GlobalState) state = stateProxy;\n else if (stateProxy) state = getGlobalState();\n else [state] = useState(new GlobalState(initialState, ssrContext));\n /* eslint-enable react-hooks/rules-of-hooks */\n return (\n <context.Provider value={state}>\n {children}\n </context.Provider>\n );\n}\n"],"file":"GlobalStateProvider.js"}
@@ -14,20 +14,7 @@ var _useAsyncData = _interopRequireDefault(require("./useAsyncData"));
14
14
  */
15
15
 
16
16
  /**
17
- * @typedef {function} AsyncCollectionLoader This is the signature of
18
- * `loader` function accepted by {@link useAsyncCollection} hook.
19
- * @param {string} id ID of the collection item to load.
20
- * @param {any} oldData Previously fetched data for this ID, if any. The loader
21
- * does not have to use it, it is provided just for convenience, when the newly
22
- * resolved data may depend on the previously fetched data.
23
- * @returns {Promise<any>} Resolves to data to be stored in the global state
24
- * for the given collection item ID.
25
- */
26
-
27
- /**
28
- * @category Hooks
29
- * @func useAsyncCollection
30
- * @desc Resolves and stores at the given `path` of global state elements of
17
+ * Resolves and stores at the given `path` of global state elements of
31
18
  * an asynchronous data collection. In other words, it is an auxiliar wrapper
32
19
  * around {@link useAsyncData}, which uses a loader which resolves to different
33
20
  * data, based on ID argument passed in, and stores data fetched for different
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useAsyncCollection.js"],"names":["useAsyncCollection","id","path","loader","options","itemPath","oldData"],"mappings":";;;;;;;;;AAIA;;AAJA;AACA;AACA;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,SAASA,kBAAT,CACbC,EADa,EAEbC,IAFa,EAGbC,MAHa,EAKb;AAAA,MADAC,OACA,uEADU,EACV;AACA,MAAMC,QAAQ,GAAGH,IAAI,aAAMA,IAAN,cAAcD,EAAd,IAAqBA,EAA1C;AACA,SAAO,2BAAaI,QAAb,EAAuB,UAACC,OAAD;AAAA,WAAaH,MAAM,CAACF,EAAD,EAAKK,OAAL,CAAnB;AAAA,GAAvB,EAAyDF,OAAzD,CAAP;AACD","sourcesContent":["/**\n * Loads and uses an item in an async collection.\n */\n\nimport useAsyncData from './useAsyncData';\n\n/**\n * @typedef {function} AsyncCollectionLoader This is the signature of\n * `loader` function accepted by {@link useAsyncCollection} hook.\n * @param {string} id ID of the collection item to load.\n * @param {any} oldData Previously fetched data for this ID, if any. The loader\n * does not have to use it, it is provided just for convenience, when the newly\n * resolved data may depend on the previously fetched data.\n * @returns {Promise<any>} Resolves to data to be stored in the global state\n * for the given collection item ID.\n */\n\n/**\n * @category Hooks\n * @func useAsyncCollection\n * @desc Resolves and stores at the given `path` of global state elements of\n * an asynchronous data collection. In other words, it is an auxiliar wrapper\n * around {@link useAsyncData}, which uses a loader which resolves to different\n * data, based on ID argument passed in, and stores data fetched for different\n * IDs in the state.\n * @param {string} id ID of the collection item to load & use.\n * @param {string} path The global state path where entire collection should be\n * stored.\n * @param {AsyncCollectionLoader} loader A loader function, which takes an\n * ID of data to load, and resolves to the corresponding data.\n * @param {object} [options] Additional options.\n * @param {any[]} [options.deps=[]] An array of dependencies, which trigger\n * data reload when changed. Given dependency changes are watched shallowly\n * (similarly to the standard React's\n * [useEffect()](https://reactjs.org/docs/hooks-reference.html#useeffect)).\n * @param {boolean} [options.noSSR] If `true`, this hook won't load data during\n * server-side rendering.\n * @param {number} [options.garbageCollectAge=maxage] The maximum age of data\n * (in milliseconds), after which they are dropped from the state when the last\n * component referencing them via `useAsyncData()` hook unmounts. Defaults to\n * `maxage` option value.\n * @param {number} [options.maxage=5 x 60 x 1000] The maximum age of\n * data (in milliseconds) acceptable to the hook's caller. If loaded data are\n * older than this value, `null` is returned instead. Defaults to 5 minutes.\n * @param {number} [options.refreshAge=maxage] The maximum age of data\n * (in milliseconds), after which their refreshment will be triggered when\n * any component referencing them via `useAsyncData()` hook (re-)renders.\n * Defaults to `maxage` value.\n * @return {{\n * data: any,\n * loading: boolean,\n * timestamp: number\n * }} Returns an object with three fields: `data` holds the actual result of\n * last `loader` invokation, if any, and if satisfies `maxage` limit; `loading`\n * is a boolean flag, which is `true` if data are being loaded (the hook is\n * waiting for `loader` function resolution); `timestamp` (in milliseconds)\n * is Unix timestamp of related data currently loaded into the global state.\n *\n * Note that loaded data, if any, are stored at the given `path` of global state\n * along with related meta-information, using slightly different state segment\n * structure (see {@link AsyncDataEnvelope}). That segment of the global state\n * can be accessed, and even modified using other hooks,\n * _e.g._ {@link useGlobalState}, but doing so you may interfere with related\n * `useAsyncData()` hooks logic.\n */\nexport default function useAsyncCollection(\n id,\n path,\n loader,\n options = {},\n) {\n const itemPath = path ? `${path}.${id}` : id;\n return useAsyncData(itemPath, (oldData) => loader(id, oldData), options);\n}\n"],"file":"useAsyncCollection.js"}
1
+ {"version":3,"sources":["../../src/useAsyncCollection.js"],"names":["useAsyncCollection","id","path","loader","options","itemPath","oldData"],"mappings":";;;;;;;;;AAIA;;AAJA;AACA;AACA;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,SAASA,kBAAT,CACbC,EADa,EAEbC,IAFa,EAGbC,MAHa,EAKb;AAAA,MADAC,OACA,uEADU,EACV;AACA,MAAMC,QAAQ,GAAGH,IAAI,aAAMA,IAAN,cAAcD,EAAd,IAAqBA,EAA1C;AACA,SAAO,2BAAaI,QAAb,EAAuB,UAACC,OAAD;AAAA,WAAaH,MAAM,CAACF,EAAD,EAAKK,OAAL,CAAnB;AAAA,GAAvB,EAAyDF,OAAzD,CAAP;AACD","sourcesContent":["/**\n * Loads and uses an item in an async collection.\n */\n\nimport useAsyncData from './useAsyncData';\n\n/**\n * Resolves and stores at the given `path` of global state elements of\n * an asynchronous data collection. In other words, it is an auxiliar wrapper\n * around {@link useAsyncData}, which uses a loader which resolves to different\n * data, based on ID argument passed in, and stores data fetched for different\n * IDs in the state.\n * @param {string} id ID of the collection item to load & use.\n * @param {string} path The global state path where entire collection should be\n * stored.\n * @param {AsyncCollectionLoader} loader A loader function, which takes an\n * ID of data to load, and resolves to the corresponding data.\n * @param {object} [options] Additional options.\n * @param {any[]} [options.deps=[]] An array of dependencies, which trigger\n * data reload when changed. Given dependency changes are watched shallowly\n * (similarly to the standard React's\n * [useEffect()](https://reactjs.org/docs/hooks-reference.html#useeffect)).\n * @param {boolean} [options.noSSR] If `true`, this hook won't load data during\n * server-side rendering.\n * @param {number} [options.garbageCollectAge=maxage] The maximum age of data\n * (in milliseconds), after which they are dropped from the state when the last\n * component referencing them via `useAsyncData()` hook unmounts. Defaults to\n * `maxage` option value.\n * @param {number} [options.maxage=5 x 60 x 1000] The maximum age of\n * data (in milliseconds) acceptable to the hook's caller. If loaded data are\n * older than this value, `null` is returned instead. Defaults to 5 minutes.\n * @param {number} [options.refreshAge=maxage] The maximum age of data\n * (in milliseconds), after which their refreshment will be triggered when\n * any component referencing them via `useAsyncData()` hook (re-)renders.\n * Defaults to `maxage` value.\n * @return {{\n * data: any,\n * loading: boolean,\n * timestamp: number\n * }} Returns an object with three fields: `data` holds the actual result of\n * last `loader` invokation, if any, and if satisfies `maxage` limit; `loading`\n * is a boolean flag, which is `true` if data are being loaded (the hook is\n * waiting for `loader` function resolution); `timestamp` (in milliseconds)\n * is Unix timestamp of related data currently loaded into the global state.\n *\n * Note that loaded data, if any, are stored at the given `path` of global state\n * along with related meta-information, using slightly different state segment\n * structure (see {@link AsyncDataEnvelope}). That segment of the global state\n * can be accessed, and even modified using other hooks,\n * _e.g._ {@link useGlobalState}, but doing so you may interfere with related\n * `useAsyncData()` hooks logic.\n */\nexport default function useAsyncCollection(\n id,\n path,\n loader,\n options = {},\n) {\n const itemPath = path ? `${path}.${id}` : id;\n return useAsyncData(itemPath, (oldData) => loader(id, oldData), options);\n}\n"],"file":"useAsyncCollection.js"}
@@ -27,9 +27,9 @@ var _useGlobalState3 = _interopRequireDefault(require("./useGlobalState"));
27
27
 
28
28
  var _utils = require("./utils");
29
29
 
30
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
30
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
31
31
 
32
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
32
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
33
33
 
34
34
  var DEFAULT_MAXAGE = 5 * 60 * 1000; // 5 minutes.
35
35
 
@@ -52,40 +52,7 @@ function load(_x, _x2, _x3, _x4) {
52
52
  return _load.apply(this, arguments);
53
53
  }
54
54
  /**
55
- * @typedef {object} AsyncDataEnvelope This type documents the structure of
56
- * global state segment, created by {@link useAsyncData} hook for storing of
57
- * loaded async data, and associated metadata.
58
- * @prop {any} data The actual loaded data.
59
- * @prop {number} numRefs The count of currently mounted components referencing
60
- * the data via `useAsyncData` hooks.
61
- * @prop {string} operationId A unique ID of the current data loading
62
- * operation, if one is in progress. Changing this ID before the operation
63
- * completes effectively cancels the ongoing operation, and instructs related
64
- * hook to ignore the operation result.
65
- *
66
- * NOTE: Server-side and client-side operation UIDs start with `S` or `C` letter
67
- * respectively. At the client side, if an envelop stores `operationId` starting
68
- * with `S` letter, it is understood as a non-terminated data loading operation
69
- * during SSR, and it is restarted at the client-side in this case.
70
- * @prop {number} timestamp Unix timestamp (in milliseconds) of the most
71
- * recently loaded `data`.
72
- */
73
-
74
- /**
75
- * @typedef {function} AsyncDataLoader This type documents the signature of
76
- * async data loader function, expected by {@link useAsyncData} hook.
77
- * @param {any} oldData Previously loaded data (_i.e._ the data currently stored
78
- * at the global state `path` managed by the corresponding `useAsyncData` hook,
79
- * which are assumed to be resolved from a previous call to the loader).
80
- * The loader does not have to use this argument, it is provided just for
81
- * convenience.
82
- * @return {Promise<any>} Async data to store to the state.
83
- */
84
-
85
- /**
86
- * @category Hooks
87
- * @func useAsyncData
88
- * @desc Resolves asynchronous data, and stores them at given `path` of global
55
+ * Resolves asynchronous data, and stores them at given `path` of global
89
56
  * state. When multiple components rely on asynchronous data at the same `path`,
90
57
  * the data are resolved once, and reused until their age is within specified
91
58
  * bounds. Once the data are stale, the hook allows to refresh them. It also
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useAsyncData.js"],"names":["DEFAULT_MAXAGE","load","path","loader","globalState","oldData","opIdPrefix","process","env","NODE_ENV","console","log","operationId","operationIdPath","set","get","data","state","groupCollapsed","timestamp","Date","now","groupEnd","useAsyncData","options","garbageCollectAge","maxage","refreshAge","undefined","numRefs","localState","ssrContext","noSSR","pending","push","numRefsPath","loadTriggered","charAt","deps","length","loading","Boolean"],"mappings":";;;;;;;;;;;;;;;;;AAIA;;AACA;;AACA;;AAEA;;AACA;;AACA;;;;;;AAEA,IAAMA,cAAc,GAAG,IAAI,EAAJ,GAAS,IAAhC,C,CAAsC;;AAEtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;SACeC,I;;;AAsCf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;kFAzHA,iBAAoBC,IAApB,EAA0BC,MAA1B,EAAkCC,WAAlC,EAA+CC,OAA/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAwDC,YAAAA,UAAxD,2DAAqE,GAArE;;AACE,gBAAIC,OAAO,CAACC,GAAR,CAAYC,QAAZ,KAAyB,YAAzB,IAAyC,yBAA7C,EAA4D;AAC1D;AACAC,cAAAA,OAAO,CAACC,GAAR,qEAC8DT,IAAI,IAAI,EADtE;AAGA;AACD;;AACKU,YAAAA,WARR,GAQsBN,UAAU,GAAG,eARnC;AASQO,YAAAA,eATR,GAS0BX,IAAI,aAAMA,IAAN,oBAA2B,aATzD;AAUEE,YAAAA,WAAW,CAACU,GAAZ,CAAgBD,eAAhB,EAAiCD,WAAjC;AAVF;AAAA,mBAWqBT,MAAM,CAACE,OAAO,IAAID,WAAW,CAACW,GAAZ,CAAgBb,IAAhB,EAAsBc,IAAlC,CAX3B;;AAAA;AAWQA,YAAAA,IAXR;AAYQC,YAAAA,KAZR,GAYgBb,WAAW,CAACW,GAAZ,CAAgBb,IAAhB,C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","sourcesContent":["/**\n * Loads and uses async data into the GlobalState path.\n */\n\nimport { cloneDeep } from 'lodash';\nimport { useEffect } from 'react';\nimport { v4 as uuid } from 'uuid';\n\nimport { getGlobalState } from './GlobalStateProvider';\nimport useGlobalState from './useGlobalState';\nimport { isDebugMode } from './utils';\n\nconst DEFAULT_MAXAGE = 5 * 60 * 1000; // 5 minutes.\n\n/**\n * Executes the data loading operation.\n * @param {string} path Data segment path inside the global state.\n * @param {function} loader Data loader.\n * @param {GlobalState} globalState The global state instance.\n * @param {any} [oldData] Optional. Previously fetched data, currently stored in\n * the state, if already fetched by the caller; otherwise, they will be fetched\n * by the load() function itself.\n * @param {string} [opIdPrefix='C'] operationId prefix to use, which should be\n * 'C' at the client-side (default), or 'S' at the server-side (within SSR\n * context).\n * @return {Promise} Resolves once the operation is done.\n * @ignore\n */\nasync function load(path, loader, globalState, oldData, opIdPrefix = 'C') {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.log(\n `ReactGlobalState: useAsyncData data (re-)loading. Path: \"${path || ''}\"`,\n );\n /* eslint-enable no-console */\n }\n const operationId = opIdPrefix + uuid();\n const operationIdPath = path ? `${path}.operationId` : 'operationId';\n globalState.set(operationIdPath, operationId);\n const data = await loader(oldData || globalState.get(path).data);\n const state = globalState.get(path);\n if (operationId === state.operationId) {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupCollapsed(\n `ReactGlobalState: useAsyncData data (re-)loaded. Path: \"${\n path || ''\n }\"`,\n );\n console.log('Data:', cloneDeep(data));\n /* eslint-enable no-console */\n }\n globalState.set(path, {\n ...state,\n data,\n operationId: '',\n timestamp: Date.now(),\n });\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupEnd();\n /* eslint-enable no-console */\n }\n }\n}\n\n/**\n * @typedef {object} AsyncDataEnvelope This type documents the structure of\n * global state segment, created by {@link useAsyncData} hook for storing of\n * loaded async data, and associated metadata.\n * @prop {any} data The actual loaded data.\n * @prop {number} numRefs The count of currently mounted components referencing\n * the data via `useAsyncData` hooks.\n * @prop {string} operationId A unique ID of the current data loading\n * operation, if one is in progress. Changing this ID before the operation\n * completes effectively cancels the ongoing operation, and instructs related\n * hook to ignore the operation result.\n *\n * NOTE: Server-side and client-side operation UIDs start with `S` or `C` letter\n * respectively. At the client side, if an envelop stores `operationId` starting\n * with `S` letter, it is understood as a non-terminated data loading operation\n * during SSR, and it is restarted at the client-side in this case.\n * @prop {number} timestamp Unix timestamp (in milliseconds) of the most\n * recently loaded `data`.\n */\n\n/**\n * @typedef {function} AsyncDataLoader This type documents the signature of\n * async data loader function, expected by {@link useAsyncData} hook.\n * @param {any} oldData Previously loaded data (_i.e._ the data currently stored\n * at the global state `path` managed by the corresponding `useAsyncData` hook,\n * which are assumed to be resolved from a previous call to the loader).\n * The loader does not have to use this argument, it is provided just for\n * convenience.\n * @return {Promise<any>} Async data to store to the state.\n */\n\n/**\n * @category Hooks\n * @func useAsyncData\n * @desc Resolves asynchronous data, and stores them at given `path` of global\n * state. When multiple components rely on asynchronous data at the same `path`,\n * the data are resolved once, and reused until their age is within specified\n * bounds. Once the data are stale, the hook allows to refresh them. It also\n * garbage-collects stale data from the global state when the last component\n * relying on them is unmounted.\n * @param {string} path Dot-delimitered state path, where data envelop is\n * stored.\n * @param {AsyncDataLoader} loader Asynchronous function which resolves (loads)\n * data, which should be stored at the global state `path`. When multiple\n * components\n * use `useAsyncData()` hook for the same `path`, the library assumes that all\n * hook instances are called with the same `loader` (_i.e._ whichever of these\n * loaders is used to resolve async data, the result is acceptable to be reused\n * in all related components).\n * @param {object} [options] Additional options.\n * @param {any[]} [options.deps=[]] An array of dependencies, which trigger\n * data reload when changed. Given dependency changes are watched shallowly\n * (similarly to the standard React's\n * [useEffect()](https://reactjs.org/docs/hooks-reference.html#useeffect)).\n * @param {boolean} [options.noSSR] If `true`, this hook won't load data during\n * server-side rendering.\n * @param {number} [options.garbageCollectAge=maxage] The maximum age of data\n * (in milliseconds), after which they are dropped from the state when the last\n * component referencing them via `useAsyncData()` hook unmounts. Defaults to\n * `maxage` option value.\n * @param {number} [options.maxage=5 x 60 x 1000] The maximum age of\n * data (in milliseconds) acceptable to the hook's caller. If loaded data are\n * older than this value, `null` is returned instead. Defaults to 5 minutes.\n * @param {number} [options.refreshAge=maxage] The maximum age of data\n * (in milliseconds), after which their refreshment will be triggered when\n * any component referencing them via `useAsyncData()` hook (re-)renders.\n * Defaults to `maxage` value.\n * @return {{\n * data: any,\n * loading: boolean,\n * timestamp: number\n * }} Returns an object with three fields: `data` holds the actual result of\n * last `loader` invokation, if any, and if satisfies `maxage` limit; `loading`\n * is a boolean flag, which is `true` if data are being loaded (the hook is\n * waiting for `loader` function resolution); `timestamp` (in milliseconds)\n * is Unix timestamp of related data currently loaded into the global state.\n *\n * Note that loaded data, if any, are stored at the given `path` of global state\n * along with related meta-information, using slightly different state segment\n * structure (see {@link AsyncDataEnvelope}). That segment of the global state\n * can be accessed, and even modified using other hooks,\n * _e.g._ {@link useGlobalState}, but doing so you may interfere with related\n * `useAsyncData()` hooks logic.\n */\nexport default function useAsyncData(\n path,\n loader,\n options = {},\n) {\n let { garbageCollectAge, maxage, refreshAge } = options;\n if (maxage === undefined) maxage = DEFAULT_MAXAGE;\n if (refreshAge === undefined) refreshAge = maxage;\n if (garbageCollectAge === undefined) garbageCollectAge = maxage;\n\n const globalState = getGlobalState();\n const [localState] = useGlobalState(path, {\n data: null,\n numRefs: 0,\n operationId: '',\n timestamp: 0,\n });\n\n if (globalState.ssrContext && !options.noSSR) {\n const state = globalState.get(path);\n if (!state.timestamp && !state.operationId) {\n globalState.ssrContext.pending.push(\n load(path, loader, globalState, state.data, 'S'),\n );\n }\n } else {\n // This takes care about the client-side reference counting, and garbage\n // collection.\n //\n // Note: the Rules of Hook below are violated by conditional call to a hook,\n // but as the condition is actually server-side or client-side environment,\n // it is effectively non-conditional at the runtime.\n //\n // TODO: Though, maybe there is a way to refactor it into a cleaner code.\n // The same applies to other useEffect() hooks below.\n useEffect(() => { // eslint-disable-line react-hooks/rules-of-hooks\n const numRefsPath = path ? `${path}.numRefs` : 'numRefs';\n const numRefs = globalState.get(numRefsPath);\n globalState.set(numRefsPath, numRefs + 1);\n return () => {\n const state = globalState.get(path);\n if (\n state.numRefs === 1\n && garbageCollectAge < Date.now() - state.timestamp\n ) {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.log(\n `ReactGlobalState - useAsyncData garbage collected at path ${\n path || ''\n }`,\n );\n /* eslint-enable no-console */\n }\n globalState.set(path, {\n ...state,\n data: null,\n numRefs: 0,\n timestamp: 0,\n });\n } else globalState.set(numRefsPath, state.numRefs - 1);\n };\n }, [garbageCollectAge, globalState, path]);\n\n // Note: a bunch of Rules of Hooks ignored belows because in our very\n // special case the otherwise wrong behavior is actually what we need.\n\n // Data loading and refreshing.\n let loadTriggered = false;\n useEffect(() => { // eslint-disable-line react-hooks/rules-of-hooks\n const state = globalState.get(path);\n if (refreshAge < Date.now() - state.timestamp\n && (!state.operationId || state.operationId.charAt() === 'S')) {\n load(path, loader, globalState, state.data);\n loadTriggered = true; // eslint-disable-line react-hooks/exhaustive-deps\n }\n });\n\n const deps = options.deps || [];\n useEffect(() => { // eslint-disable-line react-hooks/rules-of-hooks\n if (!loadTriggered && deps.length) load(path, loader, globalState);\n }, deps); // eslint-disable-line react-hooks/exhaustive-deps\n }\n\n return {\n data: maxage < Date.now() - localState.timestamp ? null : localState.data,\n loading: Boolean(localState.operationId),\n timestamp: localState.timestamp,\n };\n}\n"],"file":"useAsyncData.js"}
1
+ {"version":3,"sources":["../../src/useAsyncData.js"],"names":["DEFAULT_MAXAGE","load","path","loader","globalState","oldData","opIdPrefix","process","env","NODE_ENV","console","log","operationId","operationIdPath","set","get","data","state","groupCollapsed","timestamp","Date","now","groupEnd","useAsyncData","options","garbageCollectAge","maxage","refreshAge","undefined","numRefs","localState","ssrContext","noSSR","pending","push","numRefsPath","loadTriggered","charAt","deps","length","loading","Boolean"],"mappings":"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","sourcesContent":["/**\n * Loads and uses async data into the GlobalState path.\n */\n\nimport { cloneDeep } from 'lodash';\nimport { useEffect } from 'react';\nimport { v4 as uuid } from 'uuid';\n\nimport { getGlobalState } from './GlobalStateProvider';\nimport useGlobalState from './useGlobalState';\nimport { isDebugMode } from './utils';\n\nconst DEFAULT_MAXAGE = 5 * 60 * 1000; // 5 minutes.\n\n/**\n * Executes the data loading operation.\n * @param {string} path Data segment path inside the global state.\n * @param {function} loader Data loader.\n * @param {GlobalState} globalState The global state instance.\n * @param {any} [oldData] Optional. Previously fetched data, currently stored in\n * the state, if already fetched by the caller; otherwise, they will be fetched\n * by the load() function itself.\n * @param {string} [opIdPrefix='C'] operationId prefix to use, which should be\n * 'C' at the client-side (default), or 'S' at the server-side (within SSR\n * context).\n * @return {Promise} Resolves once the operation is done.\n * @ignore\n */\nasync function load(path, loader, globalState, oldData, opIdPrefix = 'C') {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.log(\n `ReactGlobalState: useAsyncData data (re-)loading. Path: \"${path || ''}\"`,\n );\n /* eslint-enable no-console */\n }\n const operationId = opIdPrefix + uuid();\n const operationIdPath = path ? `${path}.operationId` : 'operationId';\n globalState.set(operationIdPath, operationId);\n const data = await loader(oldData || globalState.get(path).data);\n const state = globalState.get(path);\n if (operationId === state.operationId) {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupCollapsed(\n `ReactGlobalState: useAsyncData data (re-)loaded. Path: \"${\n path || ''\n }\"`,\n );\n console.log('Data:', cloneDeep(data));\n /* eslint-enable no-console */\n }\n globalState.set(path, {\n ...state,\n data,\n operationId: '',\n timestamp: Date.now(),\n });\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupEnd();\n /* eslint-enable no-console */\n }\n }\n}\n\n/**\n * Resolves asynchronous data, and stores them at given `path` of global\n * state. When multiple components rely on asynchronous data at the same `path`,\n * the data are resolved once, and reused until their age is within specified\n * bounds. Once the data are stale, the hook allows to refresh them. It also\n * garbage-collects stale data from the global state when the last component\n * relying on them is unmounted.\n * @param {string} path Dot-delimitered state path, where data envelop is\n * stored.\n * @param {AsyncDataLoader} loader Asynchronous function which resolves (loads)\n * data, which should be stored at the global state `path`. When multiple\n * components\n * use `useAsyncData()` hook for the same `path`, the library assumes that all\n * hook instances are called with the same `loader` (_i.e._ whichever of these\n * loaders is used to resolve async data, the result is acceptable to be reused\n * in all related components).\n * @param {object} [options] Additional options.\n * @param {any[]} [options.deps=[]] An array of dependencies, which trigger\n * data reload when changed. Given dependency changes are watched shallowly\n * (similarly to the standard React's\n * [useEffect()](https://reactjs.org/docs/hooks-reference.html#useeffect)).\n * @param {boolean} [options.noSSR] If `true`, this hook won't load data during\n * server-side rendering.\n * @param {number} [options.garbageCollectAge=maxage] The maximum age of data\n * (in milliseconds), after which they are dropped from the state when the last\n * component referencing them via `useAsyncData()` hook unmounts. Defaults to\n * `maxage` option value.\n * @param {number} [options.maxage=5 x 60 x 1000] The maximum age of\n * data (in milliseconds) acceptable to the hook's caller. If loaded data are\n * older than this value, `null` is returned instead. Defaults to 5 minutes.\n * @param {number} [options.refreshAge=maxage] The maximum age of data\n * (in milliseconds), after which their refreshment will be triggered when\n * any component referencing them via `useAsyncData()` hook (re-)renders.\n * Defaults to `maxage` value.\n * @return {{\n * data: any,\n * loading: boolean,\n * timestamp: number\n * }} Returns an object with three fields: `data` holds the actual result of\n * last `loader` invokation, if any, and if satisfies `maxage` limit; `loading`\n * is a boolean flag, which is `true` if data are being loaded (the hook is\n * waiting for `loader` function resolution); `timestamp` (in milliseconds)\n * is Unix timestamp of related data currently loaded into the global state.\n *\n * Note that loaded data, if any, are stored at the given `path` of global state\n * along with related meta-information, using slightly different state segment\n * structure (see {@link AsyncDataEnvelope}). That segment of the global state\n * can be accessed, and even modified using other hooks,\n * _e.g._ {@link useGlobalState}, but doing so you may interfere with related\n * `useAsyncData()` hooks logic.\n */\nexport default function useAsyncData(\n path,\n loader,\n options = {},\n) {\n let { garbageCollectAge, maxage, refreshAge } = options;\n if (maxage === undefined) maxage = DEFAULT_MAXAGE;\n if (refreshAge === undefined) refreshAge = maxage;\n if (garbageCollectAge === undefined) garbageCollectAge = maxage;\n\n const globalState = getGlobalState();\n const [localState] = useGlobalState(path, {\n data: null,\n numRefs: 0,\n operationId: '',\n timestamp: 0,\n });\n\n if (globalState.ssrContext && !options.noSSR) {\n const state = globalState.get(path);\n if (!state.timestamp && !state.operationId) {\n globalState.ssrContext.pending.push(\n load(path, loader, globalState, state.data, 'S'),\n );\n }\n } else {\n // This takes care about the client-side reference counting, and garbage\n // collection.\n //\n // Note: the Rules of Hook below are violated by conditional call to a hook,\n // but as the condition is actually server-side or client-side environment,\n // it is effectively non-conditional at the runtime.\n //\n // TODO: Though, maybe there is a way to refactor it into a cleaner code.\n // The same applies to other useEffect() hooks below.\n useEffect(() => { // eslint-disable-line react-hooks/rules-of-hooks\n const numRefsPath = path ? `${path}.numRefs` : 'numRefs';\n const numRefs = globalState.get(numRefsPath);\n globalState.set(numRefsPath, numRefs + 1);\n return () => {\n const state = globalState.get(path);\n if (\n state.numRefs === 1\n && garbageCollectAge < Date.now() - state.timestamp\n ) {\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.log(\n `ReactGlobalState - useAsyncData garbage collected at path ${\n path || ''\n }`,\n );\n /* eslint-enable no-console */\n }\n globalState.set(path, {\n ...state,\n data: null,\n numRefs: 0,\n timestamp: 0,\n });\n } else globalState.set(numRefsPath, state.numRefs - 1);\n };\n }, [garbageCollectAge, globalState, path]);\n\n // Note: a bunch of Rules of Hooks ignored belows because in our very\n // special case the otherwise wrong behavior is actually what we need.\n\n // Data loading and refreshing.\n let loadTriggered = false;\n useEffect(() => { // eslint-disable-line react-hooks/rules-of-hooks\n const state = globalState.get(path);\n if (refreshAge < Date.now() - state.timestamp\n && (!state.operationId || state.operationId.charAt() === 'S')) {\n load(path, loader, globalState, state.data);\n loadTriggered = true; // eslint-disable-line react-hooks/exhaustive-deps\n }\n });\n\n const deps = options.deps || [];\n useEffect(() => { // eslint-disable-line react-hooks/rules-of-hooks\n if (!loadTriggered && deps.length) load(path, loader, globalState);\n }, deps); // eslint-disable-line react-hooks/exhaustive-deps\n }\n\n return {\n data: maxage < Date.now() - localState.timestamp ? null : localState.data,\n loading: Boolean(localState.operationId),\n timestamp: localState.timestamp,\n };\n}\n"],"file":"useAsyncData.js"}
@@ -20,9 +20,7 @@ var _utils = require("./utils");
20
20
  // Hook for updates of global state.
21
21
 
22
22
  /**
23
- * @category Hooks
24
- * @func useGlobalState
25
- * @desc The primary hook for interacting with the global state, modeled after
23
+ * The primary hook for interacting with the global state, modeled after
26
24
  * the standard React's
27
25
  * [useState](https://reactjs.org/docs/hooks-reference.html#usestate).
28
26
  * It subscribes a component to a given `path` of global state, and provides
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useGlobalState.js"],"names":["useGlobalState","path","initialValue","globalState","state","get","value","set","localState","setLocalState","callback","active","newState","watch","unWatch","ref","current","setter","newValue","process","env","NODE_ENV","console","groupCollapsed","log","groupEnd"],"mappings":"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","sourcesContent":["// Hook for updates of global state.\n\nimport { cloneDeep, isFunction, isUndefined } from 'lodash';\nimport { useEffect, useRef, useState } from 'react';\n\nimport { getGlobalState } from './GlobalStateProvider';\nimport { isDebugMode } from './utils';\n\n/**\n * @category Hooks\n * @func useGlobalState\n * @desc The primary hook for interacting with the global state, modeled after\n * the standard React's\n * [useState](https://reactjs.org/docs/hooks-reference.html#usestate).\n * It subscribes a component to a given `path` of global state, and provides\n * a function to update it. Each time the value at `path` changes, the hook\n * triggers re-render of its host component.\n *\n * **Note:**\n * - For performance, the library does not copy objects written to / read from\n * global state paths. You MUST NOT manually mutate returned state values,\n * or change objects already written into the global state, without explicitly\n * clonning them first yourself.\n * - State update notifications are asynchronous. When your code does multiple\n * global state updates in the same React rendering cycle, all state update\n * notifications are queued and dispatched together, after the current\n * rendering cycle. In other words, in any given rendering cycle the global\n * state values are \"fixed\", and all changes becomes visible at once in the\n * next triggered rendering pass.\n *\n * @param {string} [path] Dot-delimitered state path. It can be undefined to\n * subscribe for entire state.\n *\n * Under-the-hood state values are read and written using `lodash`\n * [_.get()](https://lodash.com/docs/4.17.15#get) and\n * [_.set()](https://lodash.com/docs/4.17.15#set) methods, thus it is safe\n * to access state paths which have not been created before.\n * @param {any} [initialValue] Initial value to set at the `path`, or its\n * factory:\n * - If a function is given, it will act similar to\n * [the lazy initial state of the standard React's useState()](https://reactjs.org/docs/hooks-reference.html#lazy-initial-state):\n * only if the value at `path` is `undefined`, the function will be executed,\n * and the value it returns will be written to the `path`.\n * - Otherwise, the given value itself will be written to the `path`,\n * if the current value at `path` is `undefined`.\n * @return {Array} It returs an array with two elements: `[value, setValue]`:\n *\n * - The `value` is the current value at given `path`.\n *\n * - The `setValue()` is setter function to write a new value to the `path`.\n *\n * Similar to the standard React's `useState()`, it supports\n * [functional value updates](https://reactjs.org/docs/hooks-reference.html#functional-updates):\n * if `setValue()` is called with a function as argument, that function will\n * be called and its return value will be written to `path`. Otherwise,\n * the argument of `setValue()` itself is written to `path`.\n *\n * Also, similar to the standard React's state setters, `setValue()` is\n * stable function: it does not change between component re-renders.\n */\nexport default function useGlobalState(path, initialValue) {\n const globalState = getGlobalState();\n let state = globalState.get(path);\n if (isUndefined(state) && !isUndefined(initialValue)) {\n const value = isFunction(initialValue) ? initialValue() : initialValue;\n state = globalState.set(path, value);\n }\n const [\n localState,\n setLocalState,\n ] = useState(() => state);\n\n useEffect(() => {\n // Note: the \"callback.active\" flag below is needed to workaround the issue\n // https://github.com/birdofpreyru/react-global-state/issues/33,\n // which, unfortunately, I am not able to reproduce in test environment,\n // but I definitely seen it in the wild.\n const callback = () => {\n if (callback.active) {\n const newState = globalState.get(path);\n if (newState !== localState) setLocalState(() => newState);\n }\n };\n callback.active = true;\n globalState.watch(callback);\n callback();\n return () => {\n delete callback.active;\n globalState.unWatch(callback);\n };\n }, [globalState, localState, path]);\n\n const ref = useRef();\n if (!ref.current) {\n ref.current = {\n localState,\n path,\n setter: (value) => {\n const newValue = isFunction(value)\n ? value(ref.current.localState) : value;\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupCollapsed(\n `ReactGlobalState - useGlobalState setter triggered for path ${\n ref.current.path || ''\n }`,\n );\n console.log('New value:', cloneDeep(newValue));\n console.groupEnd();\n /* eslint-enable no-console */\n }\n\n globalState.set(ref.current.path, newValue);\n\n // The update of local state here is important for managed inputs:\n // if we wait until the global state change notification is delivered\n // (which happens after the next React render), React won't conserve\n // the text cursor inside the currently focused input field (the cursor\n // will jump to the field end, like if the value was changed not by\n // keyboard input).\n setLocalState(() => newValue);\n },\n };\n } else {\n ref.current.localState = localState;\n ref.current.path = path;\n }\n\n return [\n localState,\n ref.current.setter,\n ];\n}\n"],"file":"useGlobalState.js"}
1
+ {"version":3,"sources":["../../src/useGlobalState.js"],"names":["useGlobalState","path","initialValue","globalState","state","get","value","set","localState","setLocalState","callback","active","newState","watch","unWatch","ref","current","setter","newValue","process","env","NODE_ENV","console","groupCollapsed","log","groupEnd"],"mappings":"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","sourcesContent":["// Hook for updates of global state.\n\nimport { cloneDeep, isFunction, isUndefined } from 'lodash';\nimport { useEffect, useRef, useState } from 'react';\n\nimport { getGlobalState } from './GlobalStateProvider';\nimport { isDebugMode } from './utils';\n\n/**\n * The primary hook for interacting with the global state, modeled after\n * the standard React's\n * [useState](https://reactjs.org/docs/hooks-reference.html#usestate).\n * It subscribes a component to a given `path` of global state, and provides\n * a function to update it. Each time the value at `path` changes, the hook\n * triggers re-render of its host component.\n *\n * **Note:**\n * - For performance, the library does not copy objects written to / read from\n * global state paths. You MUST NOT manually mutate returned state values,\n * or change objects already written into the global state, without explicitly\n * clonning them first yourself.\n * - State update notifications are asynchronous. When your code does multiple\n * global state updates in the same React rendering cycle, all state update\n * notifications are queued and dispatched together, after the current\n * rendering cycle. In other words, in any given rendering cycle the global\n * state values are \"fixed\", and all changes becomes visible at once in the\n * next triggered rendering pass.\n *\n * @param {string} [path] Dot-delimitered state path. It can be undefined to\n * subscribe for entire state.\n *\n * Under-the-hood state values are read and written using `lodash`\n * [_.get()](https://lodash.com/docs/4.17.15#get) and\n * [_.set()](https://lodash.com/docs/4.17.15#set) methods, thus it is safe\n * to access state paths which have not been created before.\n * @param {any} [initialValue] Initial value to set at the `path`, or its\n * factory:\n * - If a function is given, it will act similar to\n * [the lazy initial state of the standard React's useState()](https://reactjs.org/docs/hooks-reference.html#lazy-initial-state):\n * only if the value at `path` is `undefined`, the function will be executed,\n * and the value it returns will be written to the `path`.\n * - Otherwise, the given value itself will be written to the `path`,\n * if the current value at `path` is `undefined`.\n * @return {Array} It returs an array with two elements: `[value, setValue]`:\n *\n * - The `value` is the current value at given `path`.\n *\n * - The `setValue()` is setter function to write a new value to the `path`.\n *\n * Similar to the standard React's `useState()`, it supports\n * [functional value updates](https://reactjs.org/docs/hooks-reference.html#functional-updates):\n * if `setValue()` is called with a function as argument, that function will\n * be called and its return value will be written to `path`. Otherwise,\n * the argument of `setValue()` itself is written to `path`.\n *\n * Also, similar to the standard React's state setters, `setValue()` is\n * stable function: it does not change between component re-renders.\n */\nexport default function useGlobalState(path, initialValue) {\n const globalState = getGlobalState();\n let state = globalState.get(path);\n if (isUndefined(state) && !isUndefined(initialValue)) {\n const value = isFunction(initialValue) ? initialValue() : initialValue;\n state = globalState.set(path, value);\n }\n const [\n localState,\n setLocalState,\n ] = useState(() => state);\n\n useEffect(() => {\n // Note: the \"callback.active\" flag below is needed to workaround the issue\n // https://github.com/birdofpreyru/react-global-state/issues/33,\n // which, unfortunately, I am not able to reproduce in test environment,\n // but I definitely seen it in the wild.\n const callback = () => {\n if (callback.active) {\n const newState = globalState.get(path);\n if (newState !== localState) setLocalState(() => newState);\n }\n };\n callback.active = true;\n globalState.watch(callback);\n callback();\n return () => {\n delete callback.active;\n globalState.unWatch(callback);\n };\n }, [globalState, localState, path]);\n\n const ref = useRef();\n if (!ref.current) {\n ref.current = {\n localState,\n path,\n setter: (value) => {\n const newValue = isFunction(value)\n ? value(ref.current.localState) : value;\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupCollapsed(\n `ReactGlobalState - useGlobalState setter triggered for path ${\n ref.current.path || ''\n }`,\n );\n console.log('New value:', cloneDeep(newValue));\n console.groupEnd();\n /* eslint-enable no-console */\n }\n\n globalState.set(ref.current.path, newValue);\n\n // The update of local state here is important for managed inputs:\n // if we wait until the global state change notification is delivered\n // (which happens after the next React render), React won't conserve\n // the text cursor inside the currently focused input field (the cursor\n // will jump to the field end, like if the value was changed not by\n // keyboard input).\n setLocalState(() => newValue);\n },\n };\n } else {\n ref.current.localState = localState;\n ref.current.path = path;\n }\n\n return [\n localState,\n ref.current.setter,\n ];\n}\n"],"file":"useGlobalState.js"}
@@ -8,18 +8,6 @@ exports.isDebugMode = isDebugMode;
8
8
 
9
9
  // Auxiliary stuff.
10
10
 
11
- /**
12
- * @global
13
- * @const REACT_GLOBAL_STATE_DEBUG
14
- * @desc `REACT_GLOBAL_STATE_DEBUG` is an environment variable you can set
15
- * to any truthy value for Node (or, in case of client-side bundle, inject
16
- * using Webpack's
17
- * [EnvironmentPlugin](https://webpack.js.org/plugins/environment-plugin/))
18
- * to enable debug logging by `react-global-state` library. In either case,
19
- * the logging is enabled in non-production code only, which is tested by
20
- * `process.env.NODE_ENV` value being distinct from `production`.
21
- */
22
-
23
11
  /**
24
12
  * Returns 'true' if debug logging should be performed; 'false' otherwise.
25
13
  *
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils.js"],"names":["isDebugMode","process","env","NODE_ENV","REACT_GLOBAL_STATE_DEBUG","error"],"mappings":";;;;;;;;AAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASA,WAAT,GAAuB;AAC5B,MAAI;AACF,WAAOC,OAAO,CAACC,GAAR,CAAYC,QAAZ,KAAyB,YAAzB,IACF,CAAC,CAACF,OAAO,CAACC,GAAR,CAAYE,wBADnB;AAED,GAHD,CAGE,OAAOC,KAAP,EAAc;AACd,WAAO,KAAP;AACD;AACF;;eAEc,I","sourcesContent":["// Auxiliary stuff.\n\n/**\n * @global\n * @const REACT_GLOBAL_STATE_DEBUG\n * @desc `REACT_GLOBAL_STATE_DEBUG` is an environment variable you can set\n * to any truthy value for Node (or, in case of client-side bundle, inject\n * using Webpack's\n * [EnvironmentPlugin](https://webpack.js.org/plugins/environment-plugin/))\n * to enable debug logging by `react-global-state` library. In either case,\n * the logging is enabled in non-production code only, which is tested by\n * `process.env.NODE_ENV` value being distinct from `production`.\n */\n\n/**\n * Returns 'true' if debug logging should be performed; 'false' otherwise.\n *\n * BEWARE: The actual safeguards for the debug logging still should read\n * if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n * // Some debug logging\n * }\n * to ensure that debug code is stripped out by Webpack in production mode.\n *\n * @returns {boolean}\n * @ignore\n */\nexport function isDebugMode() {\n try {\n return process.env.NODE_ENV !== 'production'\n && !!process.env.REACT_GLOBAL_STATE_DEBUG;\n } catch (error) {\n return false;\n }\n}\n\nexport default null;\n"],"file":"utils.js"}
1
+ {"version":3,"sources":["../../src/utils.js"],"names":["isDebugMode","process","env","NODE_ENV","REACT_GLOBAL_STATE_DEBUG","error"],"mappings":";;;;;;;;AAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASA,WAAT,GAAuB;AAC5B,MAAI;AACF,WAAOC,OAAO,CAACC,GAAR,CAAYC,QAAZ,KAAyB,YAAzB,IACF,CAAC,CAACF,OAAO,CAACC,GAAR,CAAYE,wBADnB;AAED,GAHD,CAGE,OAAOC,KAAP,EAAc;AACd,WAAO,KAAP;AACD;AACF;;eAEc,I","sourcesContent":["// Auxiliary stuff.\n\n/**\n * Returns 'true' if debug logging should be performed; 'false' otherwise.\n *\n * BEWARE: The actual safeguards for the debug logging still should read\n * if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n * // Some debug logging\n * }\n * to ensure that debug code is stripped out by Webpack in production mode.\n *\n * @returns {boolean}\n * @ignore\n */\nexport function isDebugMode() {\n try {\n return process.env.NODE_ENV !== 'production'\n && !!process.env.REACT_GLOBAL_STATE_DEBUG;\n } catch (error) {\n return false;\n }\n}\n\nexport default null;\n"],"file":"utils.js"}
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "@dr.pogodin/react-global-state",
3
- "version": "0.6.3",
3
+ "version": "0.6.6",
4
4
  "description": "Hook-based global state for React",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "build": "rimraf build && npm run build:node && npm run build:web",
8
8
  "build:node": "rimraf build/node && babel src --out-dir build/node --source-maps",
9
9
  "build:web": "rimraf build/web && babel src --out-dir build/web --source-maps --config-file ./babel.web.config.js",
10
- "docs": "rimraf docs && jsdoc -c config/jsdoc/config.js",
11
10
  "jest": "jest --config jest/config.json",
12
11
  "lint": "eslint --ext .js,.jsx .",
13
12
  "test": "npm run lint && npm run jest"
@@ -28,33 +27,32 @@
28
27
  "bugs": {
29
28
  "url": "https://github.com/birdofpreyru/react-global-state.git/issues"
30
29
  },
31
- "homepage": "https://dr.pogodin.studio/dev-blog/the-global-state-in-react-designed-right",
30
+ "homepage": "https://dr.pogodin.studio/docs/react-global-state/index.html",
32
31
  "dependencies": {
33
- "@babel/runtime": "^7.15.4",
32
+ "@babel/runtime": "^7.17.2",
34
33
  "lodash": "^4.17.21",
35
34
  "uuid": "^8.3.2"
36
35
  },
37
36
  "devDependencies": {
38
- "@babel/cli": "^7.15.7",
39
- "@babel/core": "^7.15.8",
40
- "@babel/node": "^7.15.8",
41
- "@babel/plugin-transform-runtime": "^7.15.8",
42
- "@babel/preset-env": "^7.15.8",
43
- "@babel/preset-react": "^7.14.5",
44
- "babel-eslint": "^10.1.0",
45
- "babel-jest": "^27.2.5",
37
+ "@babel/cli": "^7.17.6",
38
+ "@babel/core": "^7.17.5",
39
+ "@babel/eslint-parser": "^7.17.0",
40
+ "@babel/eslint-plugin": "^7.16.5",
41
+ "@babel/node": "^7.16.8",
42
+ "@babel/plugin-transform-runtime": "^7.17.0",
43
+ "@babel/preset-env": "^7.16.11",
44
+ "@babel/preset-react": "^7.16.7",
45
+ "babel-jest": "^27.5.1",
46
46
  "babel-plugin-module-resolver": "^4.1.0",
47
- "better-docs": "^2.3.2",
48
- "eslint": "^7.32.0",
49
- "eslint-config-airbnb": "^18.2.1",
47
+ "eslint": "^8.10.0",
48
+ "eslint-config-airbnb": "^19.0.4",
50
49
  "eslint-import-resolver-babel-module": "^5.3.1",
51
- "eslint-plugin-import": "^2.25.2",
52
- "eslint-plugin-jest": "^25.0.6",
53
- "eslint-plugin-jsx-a11y": "^6.4.1",
54
- "eslint-plugin-react": "^7.26.1",
55
- "eslint-plugin-react-hooks": "^4.2.0",
56
- "jest": "^27.2.5",
57
- "jsdoc": "^3.6.7",
50
+ "eslint-plugin-import": "^2.25.4",
51
+ "eslint-plugin-jest": "^26.1.1",
52
+ "eslint-plugin-jsx-a11y": "^6.5.1",
53
+ "eslint-plugin-react": "^7.29.2",
54
+ "eslint-plugin-react-hooks": "^4.3.0",
55
+ "jest": "^27.5.1",
58
56
  "mockdate": "^3.0.5",
59
57
  "pretty": "^2.0.0",
60
58
  "react": "^17.0.2",