@dr.pogodin/react-global-state 0.15.0 → 0.16.0
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/build/common/GlobalState.js.map +1 -1
- package/build/common/GlobalStateProvider.js +5 -4
- package/build/common/GlobalStateProvider.js.map +1 -1
- package/build/common/index.js +12 -21
- package/build/common/index.js.map +1 -1
- package/build/common/useAsyncCollection.js +190 -44
- package/build/common/useAsyncCollection.js.map +1 -1
- package/build/common/useAsyncData.js +49 -59
- package/build/common/useAsyncData.js.map +1 -1
- package/build/common/useGlobalState.js.map +1 -1
- package/build/module/GlobalState.js.map +1 -1
- package/build/module/GlobalStateProvider.js +3 -2
- package/build/module/GlobalStateProvider.js.map +1 -1
- package/build/module/index.js +1 -2
- package/build/module/index.js.map +1 -1
- package/build/module/useAsyncCollection.js +208 -45
- package/build/module/useAsyncCollection.js.map +1 -1
- package/build/module/useAsyncData.js +49 -60
- package/build/module/useAsyncData.js.map +1 -1
- package/build/module/useGlobalState.js.map +1 -1
- package/build/types/GlobalStateProvider.d.ts +2 -2
- package/build/types/index.d.ts +3 -4
- package/build/types/useAsyncCollection.d.ts +29 -46
- package/build/types/useAsyncData.d.ts +28 -46
- package/build/types/useGlobalState.d.ts +2 -0
- package/package.json +17 -16
- package/src/GlobalState.ts +5 -5
- package/src/GlobalStateProvider.tsx +5 -5
- package/src/index.ts +12 -2
- package/src/useAsyncCollection.ts +355 -64
- package/src/useAsyncData.ts +66 -76
- package/src/useGlobalState.ts +13 -0
- package/tsconfig.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGlobalState.js","names":["isFunction","useEffect","useRef","useSyncExternalStore","Emitter","getGlobalState","cloneDeepForLog","isDebugMode","useGlobalState","path","initialValue","globalState","ref","rc","current","emitter","setter","value","newState","get","process","env","NODE_ENV","_rc$path","console","groupCollapsed","log","groupEnd","set","state","emit","subscribe","addListener","bind","watcher","initialState","watch","unWatch"],"sources":["../../src/useGlobalState.ts"],"sourcesContent":["// Hook for updates of global state.\n\nimport { isFunction } from 'lodash';\nimport { useEffect, useRef, useSyncExternalStore } from 'react';\n\nimport { Emitter } from '@dr.pogodin/js-utils';\n\nimport GlobalState from './GlobalState';\nimport { getGlobalState } from './GlobalStateProvider';\n\nimport {\n type CallbackT,\n type ForceT,\n type LockT,\n type TypeLock,\n type ValueAtPathT,\n type ValueOrInitializerT,\n cloneDeepForLog,\n isDebugMode,\n} from './utils';\n\nexport type SetterT<T> = React.Dispatch<React.SetStateAction<T>>;\n\ntype ListenerT = () => void;\n\ntype GlobalStateRef = {\n emitter: Emitter<[]>;\n globalState: GlobalState<unknown>;\n path: null | string | undefined;\n setter: SetterT<unknown>;\n subscribe: (listener: ListenerT) => () => void;\n state: unknown;\n watcher: CallbackT;\n};\n\nexport type UseGlobalStateResT<T> = [T, SetterT<T>];\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 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 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 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 */\n\n// \"Enforced type overload\"\nfunction useGlobalState<\n Forced extends ForceT | LockT = LockT,\n ValueT = void,\n>(\n path: null | string | undefined,\n initialValue?: ValueOrInitializerT<TypeLock<Forced, never, ValueT>>,\n): UseGlobalStateResT<TypeLock<Forced, void, ValueT>>;\n\n// \"Entire state overload\"\nfunction useGlobalState<StateT>(): UseGlobalStateResT<StateT>;\n\n// \"State evaluation overload\"\nfunction useGlobalState<\n StateT,\n PathT extends null | string | undefined,\n>(\n path: PathT,\n initialValue?: ValueOrInitializerT<ValueAtPathT<StateT, PathT, never>>\n): UseGlobalStateResT<ValueAtPathT<StateT, PathT, void>>;\n\nfunction useGlobalState(\n path?: null | string,\n initialValue?: ValueOrInitializerT<unknown>,\n): UseGlobalStateResT<any> {\n const globalState = getGlobalState();\n\n const ref = useRef<GlobalStateRef>();\n\n let rc: GlobalStateRef;\n if (!ref.current) {\n const emitter = new Emitter();\n ref.current = {\n emitter,\n globalState,\n path,\n setter: (value) => {\n const newState = isFunction(value)\n ? value(rc!.globalState.get(rc!.path))\n : value;\n\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupCollapsed(\n `ReactGlobalState - useGlobalState setter triggered for path ${\n rc!.path || ''\n }`,\n );\n console.log('New value:', cloneDeepForLog(newState, rc.path ?? ''));\n console.groupEnd();\n /* eslint-enable no-console */\n }\n rc!.globalState.set<ForceT, unknown>(rc!.path, newState);\n\n // NOTE: The regular global state's update notifications, automatically\n // triggered by the rc.globalState.set() call above, are batched, and\n // scheduled to fire asynchronosuly at a later time, which is problematic\n // for managed text inputs - if they have their value update delayed to\n // future render cycles, it will result in reset of their cursor position\n // to the value end. Calling the rc.emitter.emit() below causes a sooner\n // state update for the current component, thus working around the issue.\n // For additional details see the original issue:\n // https://github.com/birdofpreyru/react-global-state/issues/22\n if (newState !== rc!.state) rc!.emitter.emit();\n },\n state: isFunction(initialValue) ? initialValue() : initialValue,\n subscribe: emitter.addListener.bind(emitter),\n watcher: () => {\n const state = rc!.globalState.get(rc!.path);\n if (state !== rc!.state) rc!.emitter.emit();\n },\n };\n }\n rc = ref.current!;\n\n rc.globalState = globalState;\n rc.path = path;\n\n rc.state = useSyncExternalStore(\n rc.subscribe,\n () => rc!.globalState.get<ForceT, unknown>(rc!.path, { initialValue }),\n\n () => rc!.globalState.get<ForceT, unknown>(\n rc!.path,\n { initialValue, initialState: true },\n ),\n );\n\n useEffect(() => {\n const { watcher } = ref.current!;\n globalState.watch(watcher);\n watcher();\n return () => globalState.unWatch(watcher);\n }, [globalState]);\n\n useEffect(() => {\n ref.current!.watcher();\n }, [path]);\n\n return [rc.state, rc.setter];\n}\n\nexport default useGlobalState;\n\nexport interface UseGlobalStateI<StateT> {\n (): UseGlobalStateResT<StateT>;\n\n <PathT extends null | string | undefined>(\n path: PathT,\n initialValue?: ValueOrInitializerT<ValueAtPathT<StateT, PathT, never>>\n ): UseGlobalStateResT<ValueAtPathT<StateT, PathT, void>>;\n\n <Forced extends ForceT | LockT = LockT, ValueT = unknown>(\n path: null | string | undefined,\n initialValue?: ValueOrInitializerT<TypeLock<Forced, never, ValueT>>,\n ): UseGlobalStateResT<TypeLock<Forced, void, ValueT>>;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"useGlobalState.js","names":["isFunction","useEffect","useRef","useSyncExternalStore","Emitter","getGlobalState","cloneDeepForLog","isDebugMode","useGlobalState","path","initialValue","globalState","ref","rc","current","emitter","setter","value","newState","get","process","env","NODE_ENV","_rc$path","console","groupCollapsed","log","groupEnd","set","state","emit","subscribe","addListener","bind","watcher","initialState","watch","unWatch"],"sources":["../../src/useGlobalState.ts"],"sourcesContent":["// Hook for updates of global state.\n\nimport { isFunction } from 'lodash';\nimport { useEffect, useRef, useSyncExternalStore } from 'react';\n\nimport { Emitter } from '@dr.pogodin/js-utils';\n\nimport GlobalState from './GlobalState';\nimport { getGlobalState } from './GlobalStateProvider';\n\nimport {\n type CallbackT,\n type ForceT,\n type LockT,\n type TypeLock,\n type ValueAtPathT,\n type ValueOrInitializerT,\n cloneDeepForLog,\n isDebugMode,\n} from './utils';\n\nexport type SetterT<T> = React.Dispatch<React.SetStateAction<T>>;\n\ntype ListenerT = () => void;\n\ntype GlobalStateRef = {\n emitter: Emitter<[]>;\n globalState: GlobalState<unknown>;\n path: null | string | undefined;\n setter: SetterT<unknown>;\n subscribe: (listener: ListenerT) => () => void;\n state: unknown;\n watcher: CallbackT;\n};\n\nexport type UseGlobalStateResT<T> = [T, SetterT<T>];\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 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 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 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 */\n\n// \"Enforced type overload\"\nfunction useGlobalState<\n Forced extends ForceT | LockT = LockT,\n ValueT = void,\n>(\n path: null | string | undefined,\n initialValue?: ValueOrInitializerT<TypeLock<Forced, never, ValueT>>,\n): UseGlobalStateResT<TypeLock<Forced, void, ValueT>>;\n\n// \"Entire state overload\"\nfunction useGlobalState<StateT>(): UseGlobalStateResT<StateT>;\n\n// \"State evaluation overload\"\nfunction useGlobalState<\n StateT,\n PathT extends null | string | undefined,\n>(\n path: PathT,\n initialValue: ValueOrInitializerT<Exclude<ValueAtPathT<StateT, PathT, never>, undefined>>\n): UseGlobalStateResT<Exclude<ValueAtPathT<StateT, PathT, void>, undefined>>;\n\nfunction useGlobalState<\n StateT,\n PathT extends null | string | undefined,\n>(\n path: PathT,\n initialValue?: ValueOrInitializerT<ValueAtPathT<StateT, PathT, never>>\n): UseGlobalStateResT<ValueAtPathT<StateT, PathT, void>>;\n\nfunction useGlobalState(\n path?: null | string,\n initialValue?: ValueOrInitializerT<unknown>,\n): UseGlobalStateResT<any> {\n const globalState = getGlobalState();\n\n const ref = useRef<GlobalStateRef>();\n\n let rc: GlobalStateRef;\n if (!ref.current) {\n const emitter = new Emitter();\n ref.current = {\n emitter,\n globalState,\n path,\n setter: (value) => {\n const newState = isFunction(value)\n ? value(rc!.globalState.get(rc!.path))\n : value;\n\n if (process.env.NODE_ENV !== 'production' && isDebugMode()) {\n /* eslint-disable no-console */\n console.groupCollapsed(\n `ReactGlobalState - useGlobalState setter triggered for path ${\n rc!.path || ''\n }`,\n );\n console.log('New value:', cloneDeepForLog(newState, rc.path ?? ''));\n console.groupEnd();\n /* eslint-enable no-console */\n }\n rc!.globalState.set<ForceT, unknown>(rc!.path, newState);\n\n // NOTE: The regular global state's update notifications, automatically\n // triggered by the rc.globalState.set() call above, are batched, and\n // scheduled to fire asynchronosuly at a later time, which is problematic\n // for managed text inputs - if they have their value update delayed to\n // future render cycles, it will result in reset of their cursor position\n // to the value end. Calling the rc.emitter.emit() below causes a sooner\n // state update for the current component, thus working around the issue.\n // For additional details see the original issue:\n // https://github.com/birdofpreyru/react-global-state/issues/22\n if (newState !== rc!.state) rc!.emitter.emit();\n },\n state: isFunction(initialValue) ? initialValue() : initialValue,\n subscribe: emitter.addListener.bind(emitter),\n watcher: () => {\n const state = rc!.globalState.get(rc!.path);\n if (state !== rc!.state) rc!.emitter.emit();\n },\n };\n }\n rc = ref.current!;\n\n rc.globalState = globalState;\n rc.path = path;\n\n rc.state = useSyncExternalStore(\n rc.subscribe,\n () => rc!.globalState.get<ForceT, unknown>(rc!.path, { initialValue }),\n\n () => rc!.globalState.get<ForceT, unknown>(\n rc!.path,\n { initialValue, initialState: true },\n ),\n );\n\n useEffect(() => {\n const { watcher } = ref.current!;\n globalState.watch(watcher);\n watcher();\n return () => globalState.unWatch(watcher);\n }, [globalState]);\n\n useEffect(() => {\n ref.current!.watcher();\n }, [path]);\n\n return [rc.state, rc.setter];\n}\n\nexport default useGlobalState;\n\nexport interface UseGlobalStateI<StateT> {\n (): UseGlobalStateResT<StateT>;\n\n <PathT extends null | string | undefined>(\n path: PathT,\n initialValue: ValueOrInitializerT<Exclude<ValueAtPathT<StateT, PathT, never>, undefined>>\n ): UseGlobalStateResT<Exclude<ValueAtPathT<StateT, PathT, void>, undefined>>;\n\n <PathT extends null | string | undefined>(\n path: PathT,\n initialValue?: ValueOrInitializerT<ValueAtPathT<StateT, PathT, never>>\n ): UseGlobalStateResT<ValueAtPathT<StateT, PathT, void>>;\n\n <Forced extends ForceT | LockT = LockT, ValueT = unknown>(\n path: null | string | undefined,\n initialValue?: ValueOrInitializerT<TypeLock<Forced, never, ValueT>>,\n ): UseGlobalStateResT<TypeLock<Forced, void, ValueT>>;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -46,5 +46,5 @@ type GlobalStateProviderProps<StateT, SsrContextT extends SsrContext<StateT>> =
|
|
|
46
46
|
* - If `GlobalState` instance, it will be used by this provider.
|
|
47
47
|
* - If not given, a new `GlobalState` instance will be created and used.
|
|
48
48
|
*/
|
|
49
|
-
|
|
50
|
-
export
|
|
49
|
+
declare const GlobalStateProvider: <StateT, SsrContextT extends SsrContext<StateT> = SsrContext<StateT>>({ children, ...rest }: GlobalStateProviderProps<StateT, SsrContextT>) => import("react/jsx-runtime").JSX.Element;
|
|
50
|
+
export default GlobalStateProvider;
|
package/build/types/index.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import GlobalState from './GlobalState';
|
|
2
2
|
import GlobalStateProvider, { getGlobalState, getSsrContext } from './GlobalStateProvider';
|
|
3
3
|
import SsrContext from './SsrContext';
|
|
4
|
-
import useAsyncCollection, { type UseAsyncCollectionI } from './useAsyncCollection';
|
|
5
|
-
import { type UseAsyncDataI, newAsyncDataEnvelope } from './useAsyncData';
|
|
4
|
+
import useAsyncCollection, { type UseAsyncCollectionI, type UseAsyncCollectionResT } from './useAsyncCollection';
|
|
5
|
+
import { type AsyncDataEnvelopeT, type AsyncDataLoaderT, type AsyncDataReloaderT, type UseAsyncDataI, type UseAsyncDataResT, newAsyncDataEnvelope, useAsyncData } from './useAsyncData';
|
|
6
6
|
import useGlobalState, { type UseGlobalStateI } from './useGlobalState';
|
|
7
7
|
export type { AsyncCollectionLoaderT } from './useAsyncCollection';
|
|
8
|
-
export * from './useAsyncData';
|
|
9
8
|
export type { SetterT, UseGlobalStateResT } from './useGlobalState';
|
|
10
9
|
export type { ForceT, ValueOrInitializerT } from './utils';
|
|
11
|
-
export { getGlobalState, getSsrContext, GlobalState, GlobalStateProvider, SsrContext, useAsyncCollection, useGlobalState, };
|
|
10
|
+
export { type AsyncDataEnvelopeT, type AsyncDataLoaderT, type AsyncDataReloaderT, type UseAsyncCollectionResT, type UseAsyncDataResT, getGlobalState, getSsrContext, GlobalState, GlobalStateProvider, newAsyncDataEnvelope, SsrContext, useAsyncCollection, useAsyncData, useGlobalState, };
|
|
12
11
|
interface API<StateT, SsrContextT extends SsrContext<StateT> = SsrContext<StateT>> {
|
|
13
12
|
getGlobalState: typeof getGlobalState<StateT, SsrContextT>;
|
|
14
13
|
getSsrContext: typeof getSsrContext<SsrContextT>;
|
|
@@ -1,55 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Loads and uses
|
|
2
|
+
* Loads and uses item(s) in an async collection.
|
|
3
3
|
*/
|
|
4
4
|
import { type DataInEnvelopeAtPathT, type UseAsyncDataOptionsT, type UseAsyncDataResT } from './useAsyncData';
|
|
5
5
|
import { type ForceT, type LockT, type TypeLock } from './utils';
|
|
6
|
-
export type AsyncCollectionLoaderT<DataT> = (id:
|
|
6
|
+
export type AsyncCollectionLoaderT<DataT, IdT extends number | string = number | string> = (id: IdT, oldData: null | DataT, meta: {
|
|
7
|
+
isAborted: () => boolean;
|
|
8
|
+
oldDataTimestamp: number;
|
|
9
|
+
}) => DataT | Promise<DataT | null> | null;
|
|
10
|
+
export type AsyncCollectionReloaderT<DataT, IdT extends number | string = number | string> = (loader?: AsyncCollectionLoaderT<DataT, IdT>) => Promise<void>;
|
|
11
|
+
type CollectionItemT<DataT> = {
|
|
12
|
+
data: DataT | null;
|
|
13
|
+
loading: boolean;
|
|
14
|
+
timestamp: number;
|
|
15
|
+
};
|
|
16
|
+
export type UseAsyncCollectionResT<DataT, IdT extends number | string = number | string> = {
|
|
17
|
+
items: {
|
|
18
|
+
[id in IdT]: CollectionItemT<DataT>;
|
|
19
|
+
};
|
|
20
|
+
loading: boolean;
|
|
21
|
+
reload: AsyncCollectionReloaderT<DataT, IdT>;
|
|
22
|
+
timestamp: number;
|
|
23
|
+
};
|
|
7
24
|
/**
|
|
8
|
-
* Resolves and stores at the given `path` of global state elements of
|
|
9
|
-
* an asynchronous data collection.
|
|
10
|
-
* around {@link useAsyncData}, which uses a loader which resolves to different
|
|
11
|
-
* data, based on ID argument passed in, and stores data fetched for different
|
|
12
|
-
* IDs in the state.
|
|
13
|
-
* @param id ID of the collection item to load & use.
|
|
14
|
-
* @param path The global state path where entire collection should be
|
|
15
|
-
* stored.
|
|
16
|
-
* @param loader A loader function, which takes an
|
|
17
|
-
* ID of data to load, and resolves to the corresponding data.
|
|
18
|
-
* @param options Additional options.
|
|
19
|
-
* @param options.deps An array of dependencies, which trigger
|
|
20
|
-
* data reload when changed. Given dependency changes are watched shallowly
|
|
21
|
-
* (similarly to the standard React's
|
|
22
|
-
* [useEffect()](https://reactjs.org/docs/hooks-reference.html#useeffect)).
|
|
23
|
-
* @param options.noSSR If `true`, this hook won't load data during
|
|
24
|
-
* server-side rendering.
|
|
25
|
-
* @param options.garbageCollectAge The maximum age of data
|
|
26
|
-
* (in milliseconds), after which they are dropped from the state when the last
|
|
27
|
-
* component referencing them via `useAsyncData()` hook unmounts. Defaults to
|
|
28
|
-
* `maxage` option value.
|
|
29
|
-
* @param options.maxage The maximum age of
|
|
30
|
-
* data (in milliseconds) acceptable to the hook's caller. If loaded data are
|
|
31
|
-
* older than this value, `null` is returned instead. Defaults to 5 minutes.
|
|
32
|
-
* @param options.refreshAge The maximum age of data
|
|
33
|
-
* (in milliseconds), after which their refreshment will be triggered when
|
|
34
|
-
* any component referencing them via `useAsyncData()` hook (re-)renders.
|
|
35
|
-
* Defaults to `maxage` value.
|
|
36
|
-
* @return Returns an object with three fields: `data` holds the actual result of
|
|
37
|
-
* last `loader` invokation, if any, and if satisfies `maxage` limit; `loading`
|
|
38
|
-
* is a boolean flag, which is `true` if data are being loaded (the hook is
|
|
39
|
-
* waiting for `loader` function resolution); `timestamp` (in milliseconds)
|
|
40
|
-
* is Unix timestamp of related data currently loaded into the global state.
|
|
41
|
-
*
|
|
42
|
-
* Note that loaded data, if any, are stored at the given `path` of global state
|
|
43
|
-
* along with related meta-information, using slightly different state segment
|
|
44
|
-
* structure (see {@link AsyncDataEnvelope}). That segment of the global state
|
|
45
|
-
* can be accessed, and even modified using other hooks,
|
|
46
|
-
* _e.g._ {@link useGlobalState}, but doing so you may interfere with related
|
|
47
|
-
* `useAsyncData()` hooks logic.
|
|
25
|
+
* Resolves and stores at the given `path` of the global state elements of
|
|
26
|
+
* an asynchronous data collection.
|
|
48
27
|
*/
|
|
49
|
-
declare function useAsyncCollection<StateT, PathT extends null | string | undefined, IdT extends string, DataT extends DataInEnvelopeAtPathT<StateT, `${PathT}.${IdT}`> = DataInEnvelopeAtPathT<StateT, `${PathT}.${IdT}`>>(id: IdT, path: PathT, loader: AsyncCollectionLoaderT<DataT>, options?: UseAsyncDataOptionsT): UseAsyncDataResT<DataT>;
|
|
50
|
-
declare function useAsyncCollection<Forced extends ForceT | LockT = LockT, DataT = unknown>(id:
|
|
28
|
+
declare function useAsyncCollection<StateT, PathT extends null | string | undefined, IdT extends number | string, DataT extends DataInEnvelopeAtPathT<StateT, `${PathT}.${IdT}`> = DataInEnvelopeAtPathT<StateT, `${PathT}.${IdT}`>>(id: IdT, path: PathT, loader: AsyncCollectionLoaderT<DataT, IdT>, options?: UseAsyncDataOptionsT): UseAsyncDataResT<DataT>;
|
|
29
|
+
declare function useAsyncCollection<Forced extends ForceT | LockT = LockT, DataT = unknown, IdT extends number | string = number | string>(id: IdT, path: null | string | undefined, loader: AsyncCollectionLoaderT<TypeLock<Forced, void, DataT>, IdT>, options?: UseAsyncDataOptionsT): UseAsyncDataResT<TypeLock<Forced, void, DataT>>;
|
|
30
|
+
declare function useAsyncCollection<StateT, PathT extends null | string | undefined, IdT extends number | string, DataT extends DataInEnvelopeAtPathT<StateT, `${PathT}.${IdT}`> = DataInEnvelopeAtPathT<StateT, `${PathT}.${IdT}`>>(id: IdT[], path: PathT, loader: AsyncCollectionLoaderT<DataT, IdT>, options?: UseAsyncDataOptionsT): UseAsyncCollectionResT<DataT, IdT>;
|
|
31
|
+
declare function useAsyncCollection<Forced extends ForceT | LockT = LockT, DataT = unknown, IdT extends number | string = number | string>(id: IdT[], path: null | string | undefined, loader: AsyncCollectionLoaderT<TypeLock<Forced, void, DataT>, IdT>, options?: UseAsyncDataOptionsT): UseAsyncCollectionResT<DataT, IdT>;
|
|
51
32
|
export default useAsyncCollection;
|
|
52
33
|
export interface UseAsyncCollectionI<StateT> {
|
|
53
|
-
<PathT extends null | string | undefined, IdT extends string>(id: IdT, path: PathT, loader: AsyncCollectionLoaderT<DataInEnvelopeAtPathT<StateT, `${PathT}.${IdT}
|
|
54
|
-
<Forced extends ForceT | LockT = LockT, DataT = unknown>(id:
|
|
34
|
+
<PathT extends null | string | undefined, IdT extends number | string>(id: IdT, path: PathT, loader: AsyncCollectionLoaderT<DataInEnvelopeAtPathT<StateT, `${PathT}.${IdT}`>, IdT>, options?: UseAsyncDataOptionsT): UseAsyncDataResT<DataInEnvelopeAtPathT<StateT, `${PathT}.${IdT}`>>;
|
|
35
|
+
<Forced extends ForceT | LockT = LockT, DataT = unknown, IdT extends number | string = number | string>(id: IdT, path: null | string | undefined, loader: AsyncCollectionLoaderT<TypeLock<Forced, void, DataT>, IdT>, options?: UseAsyncDataOptionsT): UseAsyncDataResT<TypeLock<Forced, void, DataT>>;
|
|
36
|
+
<PathT extends null | string | undefined, IdT extends number | string>(id: IdT[], path: PathT, loader: AsyncCollectionLoaderT<DataInEnvelopeAtPathT<StateT, `${PathT}.${IdT}`>, IdT>, options?: UseAsyncDataOptionsT): UseAsyncCollectionResT<DataInEnvelopeAtPathT<StateT, `${PathT}.${IdT}`>, IdT>;
|
|
37
|
+
<Forced extends ForceT | LockT = LockT, DataT = unknown, IdT extends number | string = number | string>(id: IdT[], path: null | string | undefined, loader: AsyncCollectionLoaderT<TypeLock<Forced, void, DataT>, IdT>, options?: UseAsyncDataOptionsT): UseAsyncCollectionResT<DataT, IdT>;
|
|
55
38
|
}
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
* Loads and uses async data into the GlobalState path.
|
|
3
3
|
*/
|
|
4
4
|
import { type ForceT, type LockT, type TypeLock, type ValueAtPathT } from './utils';
|
|
5
|
-
|
|
5
|
+
import GlobalState from './GlobalState';
|
|
6
|
+
import SsrContext from './SsrContext';
|
|
7
|
+
export declare const DEFAULT_MAXAGE: number;
|
|
8
|
+
export type AsyncDataLoaderT<DataT> = (oldData: null | DataT, meta: {
|
|
9
|
+
isAborted: () => boolean;
|
|
10
|
+
oldDataTimestamp: number;
|
|
11
|
+
}) => DataT | Promise<DataT | null> | null;
|
|
6
12
|
export type AsyncDataReloaderT<DataT> = (loader?: AsyncDataLoaderT<DataT>) => Promise<void>;
|
|
7
13
|
export type AsyncDataEnvelopeT<DataT> = {
|
|
8
14
|
data: null | DataT;
|
|
@@ -10,6 +16,7 @@ export type AsyncDataEnvelopeT<DataT> = {
|
|
|
10
16
|
operationId: string;
|
|
11
17
|
timestamp: number;
|
|
12
18
|
};
|
|
19
|
+
export type OperationIdT = `${'C' | 'S'}${string}`;
|
|
13
20
|
export declare function newAsyncDataEnvelope<DataT>(initialData?: DataT | null, { numRefs, timestamp }?: {
|
|
14
21
|
numRefs?: number | undefined;
|
|
15
22
|
timestamp?: number | undefined;
|
|
@@ -27,54 +34,29 @@ export type UseAsyncDataResT<DataT> = {
|
|
|
27
34
|
reload: AsyncDataReloaderT<DataT>;
|
|
28
35
|
timestamp: number;
|
|
29
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* Executes the data loading operation.
|
|
39
|
+
* @param path Data segment path inside the global state.
|
|
40
|
+
* @param loader Data loader.
|
|
41
|
+
* @param globalState The global state instance.
|
|
42
|
+
* @param oldData Optional. Previously fetched data, currently stored in
|
|
43
|
+
* the state, if already fetched by the caller; otherwise, they will be fetched
|
|
44
|
+
* by the load() function itself.
|
|
45
|
+
* @param opIdPrefix operationId prefix to use, which should be
|
|
46
|
+
* 'C' at the client-side (default), or 'S' at the server-side (within SSR
|
|
47
|
+
* context).
|
|
48
|
+
* @return Resolves once the operation is done.
|
|
49
|
+
* @ignore
|
|
50
|
+
*/
|
|
51
|
+
export declare function load<DataT>(path: null | string | undefined, loader: AsyncDataLoaderT<DataT>, globalState: GlobalState<unknown, SsrContext<unknown>>, old?: {
|
|
52
|
+
data: DataT | null;
|
|
53
|
+
timestamp: number;
|
|
54
|
+
}, operationId?: OperationIdT): Promise<void>;
|
|
30
55
|
/**
|
|
31
56
|
* Resolves asynchronous data, and stores them at given `path` of global
|
|
32
|
-
* state.
|
|
33
|
-
* the data are resolved once, and reused until their age is within specified
|
|
34
|
-
* bounds. Once the data are stale, the hook allows to refresh them. It also
|
|
35
|
-
* garbage-collects stale data from the global state when the last component
|
|
36
|
-
* relying on them is unmounted.
|
|
37
|
-
* @param path Dot-delimitered state path, where data envelop is
|
|
38
|
-
* stored.
|
|
39
|
-
* @param loader Asynchronous function which resolves (loads)
|
|
40
|
-
* data, which should be stored at the global state `path`. When multiple
|
|
41
|
-
* components
|
|
42
|
-
* use `useAsyncData()` hook for the same `path`, the library assumes that all
|
|
43
|
-
* hook instances are called with the same `loader` (_i.e._ whichever of these
|
|
44
|
-
* loaders is used to resolve async data, the result is acceptable to be reused
|
|
45
|
-
* in all related components).
|
|
46
|
-
* @param options Additional options.
|
|
47
|
-
* @param options.deps An array of dependencies, which trigger
|
|
48
|
-
* data reload when changed. Given dependency changes are watched shallowly
|
|
49
|
-
* (similarly to the standard React's
|
|
50
|
-
* [useEffect()](https://reactjs.org/docs/hooks-reference.html#useeffect)).
|
|
51
|
-
* @param options.noSSR If `true`, this hook won't load data during
|
|
52
|
-
* server-side rendering.
|
|
53
|
-
* @param options.garbageCollectAge The maximum age of data
|
|
54
|
-
* (in milliseconds), after which they are dropped from the state when the last
|
|
55
|
-
* component referencing them via `useAsyncData()` hook unmounts. Defaults to
|
|
56
|
-
* `maxage` option value.
|
|
57
|
-
* @param options.maxage The maximum age of
|
|
58
|
-
* data (in milliseconds) acceptable to the hook's caller. If loaded data are
|
|
59
|
-
* older than this value, `null` is returned instead. Defaults to 5 minutes.
|
|
60
|
-
* @param options.refreshAge The maximum age of data
|
|
61
|
-
* (in milliseconds), after which their refreshment will be triggered when
|
|
62
|
-
* any component referencing them via `useAsyncData()` hook (re-)renders.
|
|
63
|
-
* Defaults to `maxage` value.
|
|
64
|
-
* @return Returns an object with three fields: `data` holds the actual result of
|
|
65
|
-
* last `loader` invokation, if any, and if satisfies `maxage` limit; `loading`
|
|
66
|
-
* is a boolean flag, which is `true` if data are being loaded (the hook is
|
|
67
|
-
* waiting for `loader` function resolution); `timestamp` (in milliseconds)
|
|
68
|
-
* is Unix timestamp of related data currently loaded into the global state.
|
|
69
|
-
*
|
|
70
|
-
* Note that loaded data, if any, are stored at the given `path` of global state
|
|
71
|
-
* along with related meta-information, using slightly different state segment
|
|
72
|
-
* structure (see {@link AsyncDataEnvelopeT}). That segment of the global state
|
|
73
|
-
* can be accessed, and even modified using other hooks,
|
|
74
|
-
* _e.g._ {@link useGlobalState}, but doing so you may interfere with related
|
|
75
|
-
* `useAsyncData()` hooks logic.
|
|
57
|
+
* state.
|
|
76
58
|
*/
|
|
77
|
-
export type DataInEnvelopeAtPathT<StateT, PathT extends null | string | undefined> = ValueAtPathT<StateT, PathT,
|
|
59
|
+
export type DataInEnvelopeAtPathT<StateT, PathT extends null | string | undefined> = Exclude<Extract<ValueAtPathT<StateT, PathT, void>, AsyncDataEnvelopeT<unknown>>['data'], null>;
|
|
78
60
|
declare function useAsyncData<StateT, PathT extends null | string | undefined, DataT extends DataInEnvelopeAtPathT<StateT, PathT> = DataInEnvelopeAtPathT<StateT, PathT>>(path: PathT, loader: AsyncDataLoaderT<DataT>, options?: UseAsyncDataOptionsT): UseAsyncDataResT<DataT>;
|
|
79
61
|
declare function useAsyncData<Forced extends ForceT | LockT = LockT, DataT = void>(path: null | string | undefined, loader: AsyncDataLoaderT<TypeLock<Forced, void, DataT>>, options?: UseAsyncDataOptionsT): UseAsyncDataResT<TypeLock<Forced, void, DataT>>;
|
|
80
62
|
export { useAsyncData };
|
|
@@ -53,10 +53,12 @@ export type UseGlobalStateResT<T> = [T, SetterT<T>];
|
|
|
53
53
|
*/
|
|
54
54
|
declare function useGlobalState<Forced extends ForceT | LockT = LockT, ValueT = void>(path: null | string | undefined, initialValue?: ValueOrInitializerT<TypeLock<Forced, never, ValueT>>): UseGlobalStateResT<TypeLock<Forced, void, ValueT>>;
|
|
55
55
|
declare function useGlobalState<StateT>(): UseGlobalStateResT<StateT>;
|
|
56
|
+
declare function useGlobalState<StateT, PathT extends null | string | undefined>(path: PathT, initialValue: ValueOrInitializerT<Exclude<ValueAtPathT<StateT, PathT, never>, undefined>>): UseGlobalStateResT<Exclude<ValueAtPathT<StateT, PathT, void>, undefined>>;
|
|
56
57
|
declare function useGlobalState<StateT, PathT extends null | string | undefined>(path: PathT, initialValue?: ValueOrInitializerT<ValueAtPathT<StateT, PathT, never>>): UseGlobalStateResT<ValueAtPathT<StateT, PathT, void>>;
|
|
57
58
|
export default useGlobalState;
|
|
58
59
|
export interface UseGlobalStateI<StateT> {
|
|
59
60
|
(): UseGlobalStateResT<StateT>;
|
|
61
|
+
<PathT extends null | string | undefined>(path: PathT, initialValue: ValueOrInitializerT<Exclude<ValueAtPathT<StateT, PathT, never>, undefined>>): UseGlobalStateResT<Exclude<ValueAtPathT<StateT, PathT, void>, undefined>>;
|
|
60
62
|
<PathT extends null | string | undefined>(path: PathT, initialValue?: ValueOrInitializerT<ValueAtPathT<StateT, PathT, never>>): UseGlobalStateResT<ValueAtPathT<StateT, PathT, void>>;
|
|
61
63
|
<Forced extends ForceT | LockT = LockT, ValueT = unknown>(path: null | string | undefined, initialValue?: ValueOrInitializerT<TypeLock<Forced, never, ValueT>>): UseGlobalStateResT<TypeLock<Forced, void, ValueT>>;
|
|
62
64
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dr.pogodin/react-global-state",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Hook-based global state for React",
|
|
5
5
|
"main": "./build/common/index.js",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
@@ -43,23 +43,25 @@
|
|
|
43
43
|
"node": ">=18"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@babel/runtime": "^7.
|
|
46
|
+
"@babel/runtime": "^7.25.0",
|
|
47
47
|
"@dr.pogodin/js-utils": "^0.0.12",
|
|
48
|
-
"@types/lodash": "^4.17.
|
|
48
|
+
"@types/lodash": "^4.17.7",
|
|
49
49
|
"lodash": "^4.17.21",
|
|
50
50
|
"uuid": "^10.0.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@babel/cli": "^7.24.
|
|
54
|
-
"@babel/core": "^7.
|
|
55
|
-
"@babel/eslint-parser": "^7.
|
|
56
|
-
"@babel/eslint-plugin": "^7.
|
|
57
|
-
"@babel/node": "^7.
|
|
53
|
+
"@babel/cli": "^7.24.8",
|
|
54
|
+
"@babel/core": "^7.25.2",
|
|
55
|
+
"@babel/eslint-parser": "^7.25.1",
|
|
56
|
+
"@babel/eslint-plugin": "^7.25.1",
|
|
57
|
+
"@babel/node": "^7.25.0",
|
|
58
58
|
"@babel/plugin-transform-runtime": "^7.24.7",
|
|
59
|
-
"@babel/preset-env": "^7.
|
|
59
|
+
"@babel/preset-env": "^7.25.3",
|
|
60
60
|
"@babel/preset-react": "^7.24.7",
|
|
61
61
|
"@babel/preset-typescript": "^7.24.7",
|
|
62
|
-
"@
|
|
62
|
+
"@testing-library/dom": "^10.4.0",
|
|
63
|
+
"@testing-library/react": "^16.0.0",
|
|
64
|
+
"@tsconfig/recommended": "^1.0.7",
|
|
63
65
|
"@types/jest": "^29.5.12",
|
|
64
66
|
"@types/pretty": "^2.0.3",
|
|
65
67
|
"@types/react": "^18.3.3",
|
|
@@ -74,16 +76,15 @@
|
|
|
74
76
|
"eslint-plugin-import": "^2.29.1",
|
|
75
77
|
"eslint-plugin-jest": "^28.6.0",
|
|
76
78
|
"eslint-plugin-jsx-a11y": "^6.9.0",
|
|
77
|
-
"eslint-plugin-react": "^7.
|
|
79
|
+
"eslint-plugin-react": "^7.35.0",
|
|
78
80
|
"eslint-plugin-react-hooks": "^4.6.2",
|
|
79
81
|
"jest": "^29.7.0",
|
|
80
82
|
"jest-environment-jsdom": "^29.7.0",
|
|
81
83
|
"mockdate": "^3.0.5",
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"typescript": "^
|
|
86
|
-
"typescript-eslint": "^7.14.1"
|
|
84
|
+
"rimraf": "^6.0.1",
|
|
85
|
+
"tstyche": "^2.1.1",
|
|
86
|
+
"typescript": "^5.5.4",
|
|
87
|
+
"typescript-eslint": "^8.0.0"
|
|
87
88
|
},
|
|
88
89
|
"peerDependencies": {
|
|
89
90
|
"react": "^18.3.1",
|
package/src/GlobalState.ts
CHANGED
|
@@ -97,7 +97,7 @@ export default class GlobalState<
|
|
|
97
97
|
const prevDeps = this.#dependencies[path];
|
|
98
98
|
let changed = !prevDeps || prevDeps.length !== deps.length;
|
|
99
99
|
for (let i = 0; !changed && i < deps.length; ++i) {
|
|
100
|
-
changed = prevDeps[i] !== deps[i];
|
|
100
|
+
changed = prevDeps![i] !== deps[i];
|
|
101
101
|
}
|
|
102
102
|
this.#dependencies[path] = Object.freeze(deps);
|
|
103
103
|
return changed;
|
|
@@ -141,7 +141,7 @@ export default class GlobalState<
|
|
|
141
141
|
this.#nextNotifierId = undefined;
|
|
142
142
|
const watchers = [...this.#watchers];
|
|
143
143
|
for (let i = 0; i < watchers.length; ++i) {
|
|
144
|
-
watchers[i]();
|
|
144
|
+
watchers[i]!();
|
|
145
145
|
}
|
|
146
146
|
});
|
|
147
147
|
}
|
|
@@ -245,7 +245,7 @@ export default class GlobalState<
|
|
|
245
245
|
let pos: any = root;
|
|
246
246
|
const pathSegments = toPath(`state.${path}`);
|
|
247
247
|
for (; segIdx < pathSegments.length - 1; segIdx += 1) {
|
|
248
|
-
const seg = pathSegments[segIdx]
|
|
248
|
+
const seg = pathSegments[segIdx]!;
|
|
249
249
|
const next = pos[seg];
|
|
250
250
|
if (Array.isArray(next)) pos[seg] = [...next];
|
|
251
251
|
else if (isObject(next)) pos[seg] = { ...next };
|
|
@@ -260,7 +260,7 @@ export default class GlobalState<
|
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
if (segIdx === pathSegments.length - 1) {
|
|
263
|
-
pos[pathSegments[segIdx]] = value;
|
|
263
|
+
pos[pathSegments[segIdx]!] = value;
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
this.#currentState = root.state;
|
|
@@ -283,7 +283,7 @@ export default class GlobalState<
|
|
|
283
283
|
const watchers = this.#watchers;
|
|
284
284
|
const pos = watchers.indexOf(callback);
|
|
285
285
|
if (pos >= 0) {
|
|
286
|
-
watchers[pos] = watchers[watchers.length - 1]
|
|
286
|
+
watchers[pos] = watchers[watchers.length - 1]!;
|
|
287
287
|
watchers.pop();
|
|
288
288
|
}
|
|
289
289
|
}
|
|
@@ -89,12 +89,10 @@ type GlobalStateProviderProps<
|
|
|
89
89
|
* - If `GlobalState` instance, it will be used by this provider.
|
|
90
90
|
* - If not given, a new `GlobalState` instance will be created and used.
|
|
91
91
|
*/
|
|
92
|
-
|
|
92
|
+
const GlobalStateProvider = <
|
|
93
93
|
StateT,
|
|
94
94
|
SsrContextT extends SsrContext<StateT> = SsrContext<StateT>,
|
|
95
|
-
>(
|
|
96
|
-
{ children, ...rest }: GlobalStateProviderProps<StateT, SsrContextT>,
|
|
97
|
-
) {
|
|
95
|
+
>({ children, ...rest }: GlobalStateProviderProps<StateT, SsrContextT>) => {
|
|
98
96
|
const state = useRef<GlobalState<StateT, SsrContextT>>();
|
|
99
97
|
if (!state.current) {
|
|
100
98
|
// NOTE: The last part of condition, "&& rest.stateProxy", is needed for
|
|
@@ -118,4 +116,6 @@ export default function GlobalStateProvider<
|
|
|
118
116
|
{children}
|
|
119
117
|
</context.Provider>
|
|
120
118
|
);
|
|
121
|
-
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export default GlobalStateProvider;
|
package/src/index.ts
CHANGED
|
@@ -9,10 +9,15 @@ import SsrContext from './SsrContext';
|
|
|
9
9
|
|
|
10
10
|
import useAsyncCollection, {
|
|
11
11
|
type UseAsyncCollectionI,
|
|
12
|
+
type UseAsyncCollectionResT,
|
|
12
13
|
} from './useAsyncCollection';
|
|
13
14
|
|
|
14
15
|
import {
|
|
16
|
+
type AsyncDataEnvelopeT,
|
|
17
|
+
type AsyncDataLoaderT,
|
|
18
|
+
type AsyncDataReloaderT,
|
|
15
19
|
type UseAsyncDataI,
|
|
20
|
+
type UseAsyncDataResT,
|
|
16
21
|
newAsyncDataEnvelope,
|
|
17
22
|
useAsyncData,
|
|
18
23
|
} from './useAsyncData';
|
|
@@ -21,19 +26,24 @@ import useGlobalState, { type UseGlobalStateI } from './useGlobalState';
|
|
|
21
26
|
|
|
22
27
|
export type { AsyncCollectionLoaderT } from './useAsyncCollection';
|
|
23
28
|
|
|
24
|
-
export * from './useAsyncData';
|
|
25
|
-
|
|
26
29
|
export type { SetterT, UseGlobalStateResT } from './useGlobalState';
|
|
27
30
|
|
|
28
31
|
export type { ForceT, ValueOrInitializerT } from './utils';
|
|
29
32
|
|
|
30
33
|
export {
|
|
34
|
+
type AsyncDataEnvelopeT,
|
|
35
|
+
type AsyncDataLoaderT,
|
|
36
|
+
type AsyncDataReloaderT,
|
|
37
|
+
type UseAsyncCollectionResT,
|
|
38
|
+
type UseAsyncDataResT,
|
|
31
39
|
getGlobalState,
|
|
32
40
|
getSsrContext,
|
|
33
41
|
GlobalState,
|
|
34
42
|
GlobalStateProvider,
|
|
43
|
+
newAsyncDataEnvelope,
|
|
35
44
|
SsrContext,
|
|
36
45
|
useAsyncCollection,
|
|
46
|
+
useAsyncData,
|
|
37
47
|
useGlobalState,
|
|
38
48
|
};
|
|
39
49
|
|