@apogeelabs/beacon-react-utils 1.1.0 → 1.2.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/dist/index.cjs +19 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +5 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +17 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -30,7 +30,18 @@ let lodash = require("lodash");
|
|
|
30
30
|
lodash = __toESM(lodash);
|
|
31
31
|
let mobx = require("mobx");
|
|
32
32
|
let react = require("react");
|
|
33
|
+
react = __toESM(react);
|
|
33
34
|
|
|
35
|
+
//#region src/useEffectEventShim.ts
|
|
36
|
+
const useEffectEvent = react.default.useEffectEvent ?? function useEffectEventShim(fn) {
|
|
37
|
+
const ref = (0, react.useRef)(fn);
|
|
38
|
+
(0, react.useLayoutEffect)(() => {
|
|
39
|
+
ref.current = fn;
|
|
40
|
+
});
|
|
41
|
+
return (0, react.useCallback)((...args) => ref.current(...args), []);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
//#endregion
|
|
34
45
|
//#region src/useStoreWatcher.ts
|
|
35
46
|
/**
|
|
36
47
|
* A custom React hook to watch for state changes in a beacon store.
|
|
@@ -46,19 +57,21 @@ let react = require("react");
|
|
|
46
57
|
* @param {boolean} [fireImmediately=false] - Whether to invoke onChange with the initial value.
|
|
47
58
|
*/
|
|
48
59
|
function useStoreWatcher(store, selector, onChange, fireImmediately = false) {
|
|
49
|
-
const stableSelector =
|
|
50
|
-
const stableOnChange =
|
|
60
|
+
const stableSelector = useEffectEvent(selector);
|
|
61
|
+
const stableOnChange = useEffectEvent(onChange);
|
|
51
62
|
(0, react.useEffect)(() => {
|
|
52
63
|
const disposer = (0, mobx.reaction)(() => {
|
|
53
64
|
return (0, mobx.toJS)(stableSelector(store));
|
|
54
65
|
}, (value, previousValue) => {
|
|
55
|
-
if (
|
|
66
|
+
if (previousValue === void 0 || !lodash.default.isEqual(value, previousValue)) stableOnChange(value);
|
|
56
67
|
}, { fireImmediately });
|
|
57
|
-
|
|
68
|
+
const storeCleanup = () => {
|
|
58
69
|
disposer();
|
|
59
|
-
}
|
|
70
|
+
};
|
|
71
|
+
store.registerCleanup(storeCleanup);
|
|
60
72
|
return () => {
|
|
61
73
|
disposer();
|
|
74
|
+
store.unregisterCleanup(storeCleanup);
|
|
62
75
|
};
|
|
63
76
|
}, [store, fireImmediately]);
|
|
64
77
|
}
|
|
@@ -91,6 +104,7 @@ function useStoreState(store, selector) {
|
|
|
91
104
|
}
|
|
92
105
|
|
|
93
106
|
//#endregion
|
|
107
|
+
exports.useEffectEvent = useEffectEvent;
|
|
94
108
|
exports.useStoreState = useStoreState;
|
|
95
109
|
exports.useStoreWatcher = useStoreWatcher;
|
|
96
110
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["_"],"sources":["../src/useStoreWatcher.ts","../src/useStoreState.ts"],"sourcesContent":["import type { BeaconActions, BeaconDerived, BeaconState, Store } from \"@apogeelabs/beacon\";\nimport _ from \"lodash\";\nimport { reaction, toJS } from \"mobx\";\nimport { useEffect
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["React","_"],"sources":["../src/useEffectEventShim.ts","../src/useStoreWatcher.ts","../src/useStoreState.ts"],"sourcesContent":["import React, { useRef, useCallback, useLayoutEffect } from \"react\";\n\n// React 19 DOM exposes useEffectEvent, but React Native does not.\n// This shim provides equivalent stable-callback semantics via useRef.\nexport const useEffectEvent: typeof React.useEffectEvent =\n React.useEffectEvent ??\n function useEffectEventShim<T extends (...args: any[]) => any>(fn: T): T {\n const ref = useRef(fn);\n // Mutating ref.current during render violates concurrent-mode rules.\n // useLayoutEffect ensures the update happens after commit, not during render.\n useLayoutEffect(() => {\n ref.current = fn;\n });\n return useCallback((...args: any[]) => ref.current(...args), []) as T;\n };\n","import type { BeaconActions, BeaconDerived, BeaconState, Store } from \"@apogeelabs/beacon\";\nimport _ from \"lodash\";\nimport { reaction, toJS } from \"mobx\";\nimport { useEffect } from \"react\";\nimport { useEffectEvent } from \"./useEffectEventShim\";\n\n/**\n * A custom React hook to watch for state changes in a beacon store.\n *\n * @template TState - The type of the store's state, extending BeaconState.\n * @template TDerived - The type of the store's derived values, extending BeaconDerived<TState>. If you don't have derived values, use EmptyDerived<TState>.\n * @template TActions - The type of the store's actions, extending BeaconActions<TState>. If you don't have actions, use EmptyActions.\n * @template T - The type returned by the selector function, inferred from the selector.\n *\n * @param {Store<TState, TDerived, TActions>} store - The Beacon store instance.\n * @param {(store: Store<TState, TDerived, TActions>) => T} selector - A function that extracts the part of the store to watch.\n * @param {(value: T) => void} onChange - A callback invoked with the new value when the selected state changes.\n * @param {boolean} [fireImmediately=false] - Whether to invoke onChange with the initial value.\n */\nexport function useStoreWatcher<\n TState extends BeaconState,\n TDerived extends BeaconDerived<TState>,\n TActions extends BeaconActions<TState>,\n T,\n>(\n store: Store<TState, TDerived, TActions>,\n selector: (store: Store<TState, TDerived, TActions>) => T,\n onChange: (value: T) => void,\n fireImmediately: boolean = false\n): void {\n // Use useEffectEvent to wrap callbacks so they don't need to be in the dependency array\n // This prevents unnecessary re-runs when consumers pass inline functions\n const stableSelector = useEffectEvent(selector);\n const stableOnChange = useEffectEvent(onChange);\n\n useEffect(() => {\n const disposer = reaction(\n () => {\n // toJS strips MobX observable wrappers so React sees plain values\n return toJS(stableSelector(store));\n },\n (value, previousValue) => {\n // MobX selectors can return new object references even when the underlying\n // data hasn't changed. Deep comparison prevents spurious re-renders.\n if (previousValue === undefined || !_.isEqual(value, previousValue)) {\n stableOnChange(value);\n }\n },\n { fireImmediately }\n );\n\n // This wrapper exists solely to produce a stable, distinct function reference.\n // registerCleanup and unregisterCleanup match by reference equality, so the same\n // reference must be passed to both. Do NOT \"simplify\" this to `disposer` directly —\n // every effect run would register a new reference that can never be unregistered,\n // resurrecting the stale-accumulation bug this whole feature was built to fix.\n const storeCleanup = () => {\n disposer();\n };\n\n // If the store is disposed externally, clean up the reaction too\n store.registerCleanup(storeCleanup);\n\n return () => {\n disposer();\n // Remove the store-side cleanup entry so stale references don't accumulate\n // when the component unmounts or the effect re-runs (e.g., store prop changed)\n store.unregisterCleanup(storeCleanup);\n };\n // stableSelector and stableOnChange are omitted from deps intentionally —\n // useEffectEvent keeps them stable across renders without needing to re-run the effect\n }, [store, fireImmediately]);\n}\n\nexport default useStoreWatcher;\n","import type { BeaconActions, BeaconDerived, BeaconState, Store } from \"@apogeelabs/beacon\";\nimport { toJS } from \"mobx\";\nimport { useState } from \"react\";\nimport { useStoreWatcher } from \"./useStoreWatcher\";\n\n/**\n * A React hook that subscribes to a Beacon store and returns a selected value as React state.\n *\n * Use this hook when you need a store value to participate in React's state lifecycle —\n * for example, to drive React Query parameters, to pass into hooks that don't understand\n * MobX observables, or to feed non-observer child components.\n *\n * For normal component rendering, prefer wrapping your component with `observer` from\n * `mobx-react-lite` and reading store values directly. That's simpler and more performant.\n *\n * @template TState - The type of the store's state, extending BeaconState.\n * @template TDerived - The type of the store's derived values, extending BeaconDerived<TState>.\n * @template TActions - The type of the store's actions, extending BeaconActions<TState>.\n * @template T - The type returned by the selector function, inferred from the selector.\n *\n * @param {Store<TState, TDerived, TActions>} store - The Beacon store instance.\n * @param {(store: Store<TState, TDerived, TActions>) => T} selector - A function that extracts the value to track.\n * @returns {T} The current value of the selected store slice, kept in sync via MobX reaction.\n */\nexport function useStoreState<\n TState extends BeaconState,\n TDerived extends BeaconDerived<TState>,\n TActions extends BeaconActions<TState>,\n T,\n>(\n store: Store<TState, TDerived, TActions>,\n selector: (store: Store<TState, TDerived, TActions>) => T\n): T {\n // Initializer function so the selector only runs once on mount, not on every render\n const [value, setValue] = useState<T>(() => toJS(selector(store)));\n\n // Wires MobX reactivity to React state — store changes call setValue, triggering a re-render\n useStoreWatcher(store, selector, setValue);\n\n return value;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,MAAa,iBACTA,cAAM,kBACN,SAAS,mBAAsD,IAAU;CACrE,MAAM,wBAAa,GAAG;AAGtB,kCAAsB;AAClB,MAAI,UAAU;GAChB;AACF,gCAAoB,GAAG,SAAgB,IAAI,QAAQ,GAAG,KAAK,EAAE,EAAE,CAAC;;;;;;;;;;;;;;;;;;ACMxE,SAAgB,gBAMZ,OACA,UACA,UACA,kBAA2B,OACvB;CAGJ,MAAM,iBAAiB,eAAe,SAAS;CAC/C,MAAM,iBAAiB,eAAe,SAAS;AAE/C,4BAAgB;EACZ,MAAM,oCACI;AAEF,yBAAY,eAAe,MAAM,CAAC;MAErC,OAAO,kBAAkB;AAGtB,OAAI,kBAAkB,UAAa,CAACC,eAAE,QAAQ,OAAO,cAAc,CAC/D,gBAAe,MAAM;KAG7B,EAAE,iBAAiB,CACtB;EAOD,MAAM,qBAAqB;AACvB,aAAU;;AAId,QAAM,gBAAgB,aAAa;AAEnC,eAAa;AACT,aAAU;AAGV,SAAM,kBAAkB,aAAa;;IAI1C,CAAC,OAAO,gBAAgB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;AC/ChC,SAAgB,cAMZ,OACA,UACC;CAED,MAAM,CAAC,OAAO,qDAAmC,SAAS,MAAM,CAAC,CAAC;AAGlE,iBAAgB,OAAO,UAAU,SAAS;AAE1C,QAAO"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BeaconActions, BeaconDerived, BeaconState, Store } from "@apogeelabs/beacon";
|
|
2
|
+
import React from "react";
|
|
2
3
|
|
|
3
4
|
//#region src/useStoreWatcher.d.ts
|
|
4
5
|
/**
|
|
@@ -38,5 +39,8 @@ declare function useStoreWatcher<TState extends BeaconState, TDerived extends Be
|
|
|
38
39
|
*/
|
|
39
40
|
declare function useStoreState<TState extends BeaconState, TDerived extends BeaconDerived<TState>, TActions extends BeaconActions<TState>, T>(store: Store<TState, TDerived, TActions>, selector: (store: Store<TState, TDerived, TActions>) => T): T;
|
|
40
41
|
//#endregion
|
|
41
|
-
|
|
42
|
+
//#region src/useEffectEventShim.d.ts
|
|
43
|
+
declare const useEffectEvent: typeof React.useEffectEvent;
|
|
44
|
+
//#endregion
|
|
45
|
+
export { useEffectEvent, useStoreState, useStoreWatcher };
|
|
42
46
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/useStoreWatcher.ts","../src/useStoreState.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/useStoreWatcher.ts","../src/useStoreState.ts","../src/useEffectEventShim.ts"],"mappings":";;;;;;;AAmBA;;;;;;;;;;iBAAgB,eAAA,gBACG,WAAA,mBACE,aAAA,CAAc,MAAA,oBACd,aAAA,CAAc,MAAA,KAAA,CAG/B,KAAA,EAAO,KAAA,CAAM,MAAA,EAAQ,QAAA,EAAU,QAAA,GAC/B,QAAA,GAAW,KAAA,EAAO,KAAA,CAAM,MAAA,EAAQ,QAAA,EAAU,QAAA,MAAc,CAAA,EACxD,QAAA,GAAW,KAAA,EAAO,CAAA,WAClB,eAAA;;;;;;AATJ;;;;;;;;;;;;;;;;iBCKgB,aAAA,gBACG,WAAA,mBACE,aAAA,CAAc,MAAA,oBACd,aAAA,CAAc,MAAA,KAAA,CAG/B,KAAA,EAAO,KAAA,CAAM,MAAA,EAAQ,QAAA,EAAU,QAAA,GAC/B,QAAA,GAAW,KAAA,EAAO,KAAA,CAAM,MAAA,EAAQ,QAAA,EAAU,QAAA,MAAc,CAAA,GACzD,CAAA;;;cC5BU,cAAA,SAAuB,KAAA,CAAM,cAAA"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
import { BeaconActions, BeaconDerived, BeaconState, Store } from "@apogeelabs/beacon";
|
|
2
3
|
|
|
3
4
|
//#region src/useStoreWatcher.d.ts
|
|
@@ -38,5 +39,8 @@ declare function useStoreWatcher<TState extends BeaconState, TDerived extends Be
|
|
|
38
39
|
*/
|
|
39
40
|
declare function useStoreState<TState extends BeaconState, TDerived extends BeaconDerived<TState>, TActions extends BeaconActions<TState>, T>(store: Store<TState, TDerived, TActions>, selector: (store: Store<TState, TDerived, TActions>) => T): T;
|
|
40
41
|
//#endregion
|
|
41
|
-
|
|
42
|
+
//#region src/useEffectEventShim.d.ts
|
|
43
|
+
declare const useEffectEvent: typeof React.useEffectEvent;
|
|
44
|
+
//#endregion
|
|
45
|
+
export { useEffectEvent, useStoreState, useStoreWatcher };
|
|
42
46
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/useStoreWatcher.ts","../src/useStoreState.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/useStoreWatcher.ts","../src/useStoreState.ts","../src/useEffectEventShim.ts"],"mappings":";;;;;;;AAmBA;;;;;;;;;;iBAAgB,eAAA,gBACG,WAAA,mBACE,aAAA,CAAc,MAAA,oBACd,aAAA,CAAc,MAAA,KAAA,CAG/B,KAAA,EAAO,KAAA,CAAM,MAAA,EAAQ,QAAA,EAAU,QAAA,GAC/B,QAAA,GAAW,KAAA,EAAO,KAAA,CAAM,MAAA,EAAQ,QAAA,EAAU,QAAA,MAAc,CAAA,EACxD,QAAA,GAAW,KAAA,EAAO,CAAA,WAClB,eAAA;;;;;;AATJ;;;;;;;;;;;;;;;;iBCKgB,aAAA,gBACG,WAAA,mBACE,aAAA,CAAc,MAAA,oBACd,aAAA,CAAc,MAAA,KAAA,CAG/B,KAAA,EAAO,KAAA,CAAM,MAAA,EAAQ,QAAA,EAAU,QAAA,GAC/B,QAAA,GAAW,KAAA,EAAO,KAAA,CAAM,MAAA,EAAQ,QAAA,EAAU,QAAA,MAAc,CAAA,GACzD,CAAA;;;cC5BU,cAAA,SAAuB,KAAA,CAAM,cAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import _ from "lodash";
|
|
2
2
|
import { reaction, toJS } from "mobx";
|
|
3
|
-
import { useEffect,
|
|
3
|
+
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
4
4
|
|
|
5
|
+
//#region src/useEffectEventShim.ts
|
|
6
|
+
const useEffectEvent = React.useEffectEvent ?? function useEffectEventShim(fn) {
|
|
7
|
+
const ref = useRef(fn);
|
|
8
|
+
useLayoutEffect(() => {
|
|
9
|
+
ref.current = fn;
|
|
10
|
+
});
|
|
11
|
+
return useCallback((...args) => ref.current(...args), []);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
5
15
|
//#region src/useStoreWatcher.ts
|
|
6
16
|
/**
|
|
7
17
|
* A custom React hook to watch for state changes in a beacon store.
|
|
@@ -23,13 +33,15 @@ function useStoreWatcher(store, selector, onChange, fireImmediately = false) {
|
|
|
23
33
|
const disposer = reaction(() => {
|
|
24
34
|
return toJS(stableSelector(store));
|
|
25
35
|
}, (value, previousValue) => {
|
|
26
|
-
if (
|
|
36
|
+
if (previousValue === void 0 || !_.isEqual(value, previousValue)) stableOnChange(value);
|
|
27
37
|
}, { fireImmediately });
|
|
28
|
-
|
|
38
|
+
const storeCleanup = () => {
|
|
29
39
|
disposer();
|
|
30
|
-
}
|
|
40
|
+
};
|
|
41
|
+
store.registerCleanup(storeCleanup);
|
|
31
42
|
return () => {
|
|
32
43
|
disposer();
|
|
44
|
+
store.unregisterCleanup(storeCleanup);
|
|
33
45
|
};
|
|
34
46
|
}, [store, fireImmediately]);
|
|
35
47
|
}
|
|
@@ -62,5 +74,5 @@ function useStoreState(store, selector) {
|
|
|
62
74
|
}
|
|
63
75
|
|
|
64
76
|
//#endregion
|
|
65
|
-
export { useStoreState, useStoreWatcher };
|
|
77
|
+
export { useEffectEvent, useStoreState, useStoreWatcher };
|
|
66
78
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/useStoreWatcher.ts","../src/useStoreState.ts"],"sourcesContent":["import type { BeaconActions, BeaconDerived, BeaconState, Store } from \"@apogeelabs/beacon\";\nimport _ from \"lodash\";\nimport { reaction, toJS } from \"mobx\";\nimport { useEffect
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/useEffectEventShim.ts","../src/useStoreWatcher.ts","../src/useStoreState.ts"],"sourcesContent":["import React, { useRef, useCallback, useLayoutEffect } from \"react\";\n\n// React 19 DOM exposes useEffectEvent, but React Native does not.\n// This shim provides equivalent stable-callback semantics via useRef.\nexport const useEffectEvent: typeof React.useEffectEvent =\n React.useEffectEvent ??\n function useEffectEventShim<T extends (...args: any[]) => any>(fn: T): T {\n const ref = useRef(fn);\n // Mutating ref.current during render violates concurrent-mode rules.\n // useLayoutEffect ensures the update happens after commit, not during render.\n useLayoutEffect(() => {\n ref.current = fn;\n });\n return useCallback((...args: any[]) => ref.current(...args), []) as T;\n };\n","import type { BeaconActions, BeaconDerived, BeaconState, Store } from \"@apogeelabs/beacon\";\nimport _ from \"lodash\";\nimport { reaction, toJS } from \"mobx\";\nimport { useEffect } from \"react\";\nimport { useEffectEvent } from \"./useEffectEventShim\";\n\n/**\n * A custom React hook to watch for state changes in a beacon store.\n *\n * @template TState - The type of the store's state, extending BeaconState.\n * @template TDerived - The type of the store's derived values, extending BeaconDerived<TState>. If you don't have derived values, use EmptyDerived<TState>.\n * @template TActions - The type of the store's actions, extending BeaconActions<TState>. If you don't have actions, use EmptyActions.\n * @template T - The type returned by the selector function, inferred from the selector.\n *\n * @param {Store<TState, TDerived, TActions>} store - The Beacon store instance.\n * @param {(store: Store<TState, TDerived, TActions>) => T} selector - A function that extracts the part of the store to watch.\n * @param {(value: T) => void} onChange - A callback invoked with the new value when the selected state changes.\n * @param {boolean} [fireImmediately=false] - Whether to invoke onChange with the initial value.\n */\nexport function useStoreWatcher<\n TState extends BeaconState,\n TDerived extends BeaconDerived<TState>,\n TActions extends BeaconActions<TState>,\n T,\n>(\n store: Store<TState, TDerived, TActions>,\n selector: (store: Store<TState, TDerived, TActions>) => T,\n onChange: (value: T) => void,\n fireImmediately: boolean = false\n): void {\n // Use useEffectEvent to wrap callbacks so they don't need to be in the dependency array\n // This prevents unnecessary re-runs when consumers pass inline functions\n const stableSelector = useEffectEvent(selector);\n const stableOnChange = useEffectEvent(onChange);\n\n useEffect(() => {\n const disposer = reaction(\n () => {\n // toJS strips MobX observable wrappers so React sees plain values\n return toJS(stableSelector(store));\n },\n (value, previousValue) => {\n // MobX selectors can return new object references even when the underlying\n // data hasn't changed. Deep comparison prevents spurious re-renders.\n if (previousValue === undefined || !_.isEqual(value, previousValue)) {\n stableOnChange(value);\n }\n },\n { fireImmediately }\n );\n\n // This wrapper exists solely to produce a stable, distinct function reference.\n // registerCleanup and unregisterCleanup match by reference equality, so the same\n // reference must be passed to both. Do NOT \"simplify\" this to `disposer` directly —\n // every effect run would register a new reference that can never be unregistered,\n // resurrecting the stale-accumulation bug this whole feature was built to fix.\n const storeCleanup = () => {\n disposer();\n };\n\n // If the store is disposed externally, clean up the reaction too\n store.registerCleanup(storeCleanup);\n\n return () => {\n disposer();\n // Remove the store-side cleanup entry so stale references don't accumulate\n // when the component unmounts or the effect re-runs (e.g., store prop changed)\n store.unregisterCleanup(storeCleanup);\n };\n // stableSelector and stableOnChange are omitted from deps intentionally —\n // useEffectEvent keeps them stable across renders without needing to re-run the effect\n }, [store, fireImmediately]);\n}\n\nexport default useStoreWatcher;\n","import type { BeaconActions, BeaconDerived, BeaconState, Store } from \"@apogeelabs/beacon\";\nimport { toJS } from \"mobx\";\nimport { useState } from \"react\";\nimport { useStoreWatcher } from \"./useStoreWatcher\";\n\n/**\n * A React hook that subscribes to a Beacon store and returns a selected value as React state.\n *\n * Use this hook when you need a store value to participate in React's state lifecycle —\n * for example, to drive React Query parameters, to pass into hooks that don't understand\n * MobX observables, or to feed non-observer child components.\n *\n * For normal component rendering, prefer wrapping your component with `observer` from\n * `mobx-react-lite` and reading store values directly. That's simpler and more performant.\n *\n * @template TState - The type of the store's state, extending BeaconState.\n * @template TDerived - The type of the store's derived values, extending BeaconDerived<TState>.\n * @template TActions - The type of the store's actions, extending BeaconActions<TState>.\n * @template T - The type returned by the selector function, inferred from the selector.\n *\n * @param {Store<TState, TDerived, TActions>} store - The Beacon store instance.\n * @param {(store: Store<TState, TDerived, TActions>) => T} selector - A function that extracts the value to track.\n * @returns {T} The current value of the selected store slice, kept in sync via MobX reaction.\n */\nexport function useStoreState<\n TState extends BeaconState,\n TDerived extends BeaconDerived<TState>,\n TActions extends BeaconActions<TState>,\n T,\n>(\n store: Store<TState, TDerived, TActions>,\n selector: (store: Store<TState, TDerived, TActions>) => T\n): T {\n // Initializer function so the selector only runs once on mount, not on every render\n const [value, setValue] = useState<T>(() => toJS(selector(store)));\n\n // Wires MobX reactivity to React state — store changes call setValue, triggering a re-render\n useStoreWatcher(store, selector, setValue);\n\n return value;\n}\n"],"mappings":";;;;;AAIA,MAAa,iBACT,MAAM,kBACN,SAAS,mBAAsD,IAAU;CACrE,MAAM,MAAM,OAAO,GAAG;AAGtB,uBAAsB;AAClB,MAAI,UAAU;GAChB;AACF,QAAO,aAAa,GAAG,SAAgB,IAAI,QAAQ,GAAG,KAAK,EAAE,EAAE,CAAC;;;;;;;;;;;;;;;;;;ACMxE,SAAgB,gBAMZ,OACA,UACA,UACA,kBAA2B,OACvB;CAGJ,MAAM,iBAAiB,eAAe,SAAS;CAC/C,MAAM,iBAAiB,eAAe,SAAS;AAE/C,iBAAgB;EACZ,MAAM,WAAW,eACP;AAEF,UAAO,KAAK,eAAe,MAAM,CAAC;MAErC,OAAO,kBAAkB;AAGtB,OAAI,kBAAkB,UAAa,CAAC,EAAE,QAAQ,OAAO,cAAc,CAC/D,gBAAe,MAAM;KAG7B,EAAE,iBAAiB,CACtB;EAOD,MAAM,qBAAqB;AACvB,aAAU;;AAId,QAAM,gBAAgB,aAAa;AAEnC,eAAa;AACT,aAAU;AAGV,SAAM,kBAAkB,aAAa;;IAI1C,CAAC,OAAO,gBAAgB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;AC/ChC,SAAgB,cAMZ,OACA,UACC;CAED,MAAM,CAAC,OAAO,YAAY,eAAkB,KAAK,SAAS,MAAM,CAAC,CAAC;AAGlE,iBAAgB,OAAO,UAAU,SAAS;AAE1C,QAAO"}
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"name": "Jim Cowart"
|
|
7
7
|
}
|
|
8
8
|
],
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.2.0",
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"description": "React hooks and utilities for Beacon stores",
|
|
12
12
|
"engines": {
|
|
@@ -37,14 +37,14 @@
|
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"lodash": "4.17.
|
|
40
|
+
"lodash": "^4.17.23",
|
|
41
41
|
"mobx": "^6.13.7",
|
|
42
42
|
"react": "^19.2.3",
|
|
43
|
-
"@apogeelabs/beacon": "1.
|
|
43
|
+
"@apogeelabs/beacon": "1.2.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/jest": "^29.5.5",
|
|
47
|
-
"@types/lodash": "4.17.16",
|
|
47
|
+
"@types/lodash": "^4.17.16",
|
|
48
48
|
"@types/react": "^19.2.3",
|
|
49
49
|
"eslint": "^8.0.1",
|
|
50
50
|
"eslint-config-standard": "^17.1.0",
|