synstate-react-hooks 1.0.1 → 2.0.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/README.md +42 -0
- package/dist/create-boolean-state.d.mts +1 -1
- package/dist/create-boolean-state.d.mts.map +1 -1
- package/dist/create-boolean-state.mjs +27 -16
- package/dist/create-boolean-state.mjs.map +1 -1
- package/dist/create-reducer.d.mts +1 -1
- package/dist/create-reducer.d.mts.map +1 -1
- package/dist/create-reducer.mjs +6 -3
- package/dist/create-reducer.mjs.map +1 -1
- package/dist/create-state.d.mts +1 -1
- package/dist/create-state.d.mts.map +1 -1
- package/dist/create-state.mjs +13 -13
- package/dist/create-state.mjs.map +1 -1
- package/dist/use-observable-effect.d.mts.map +1 -1
- package/dist/use-observable-effect.mjs +6 -6
- package/dist/use-observable-effect.mjs.map +1 -1
- package/dist/use-observable-value.mjs +8 -5
- package/dist/use-observable-value.mjs.map +1 -1
- package/dist/use-value-as-observable.d.mts.map +1 -1
- package/dist/use-value-as-observable.mjs +19 -13
- package/dist/use-value-as-observable.mjs.map +1 -1
- package/package.json +12 -12
- package/src/create-boolean-state.mts +1 -1
- package/src/create-reducer.mts +1 -1
- package/src/create-state.mts +1 -1
package/README.md
CHANGED
|
@@ -110,3 +110,45 @@ const UserProfile = (): React.JSX.Element => {
|
|
|
110
110
|
);
|
|
111
111
|
};
|
|
112
112
|
```
|
|
113
|
+
|
|
114
|
+
## Subscribing to Observables: `useObservableValue`
|
|
115
|
+
|
|
116
|
+
Use `useObservableValue` to read any `Observable` — including derived ones produced by `pipe` / `combine` — from a React component. It is implemented on top of `useSyncExternalStore`, so the component re-renders whenever the source emits.
|
|
117
|
+
|
|
118
|
+
### Overloads
|
|
119
|
+
|
|
120
|
+
| Signature | Return type | When to use |
|
|
121
|
+
| ------------------------------------------------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
122
|
+
| `useObservableValue<A>(obs: InitializedObservable<A>)` | `A` | The observable always has a current value (e.g. came from `createState`, or a `pipe` chain that preserves the initial value). |
|
|
123
|
+
| `useObservableValue<A>(obs: Observable<A>)` | `A \| undefined` | The observable may not have emitted yet (no initial value). |
|
|
124
|
+
| `useObservableValue<A, B = A>(obs: Observable<A>, initialValue: B)` | `A \| B` | Provide a fallback used while the observable has no value. Implemented via `Optional.unwrapOr`. |
|
|
125
|
+
|
|
126
|
+
### Example
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
import type * as React from 'react';
|
|
130
|
+
import { map, type Observable } from 'synstate';
|
|
131
|
+
import { createState, useObservableValue } from 'synstate-react-hooks';
|
|
132
|
+
|
|
133
|
+
const [useCount, setCount, { state: count$ }] = createState(0);
|
|
134
|
+
|
|
135
|
+
// Derived InitializedObservable — no fallback needed.
|
|
136
|
+
const doubled$ = count$.pipe(map((n) => n * 2));
|
|
137
|
+
|
|
138
|
+
// Imagine an Observable<string> that has no initial value
|
|
139
|
+
// (e.g. one waiting on an async source).
|
|
140
|
+
declare const userName$: Observable<string>;
|
|
141
|
+
|
|
142
|
+
const Profile = (): React.JSX.Element => {
|
|
143
|
+
const doubled = useObservableValue(doubled$); // number
|
|
144
|
+
|
|
145
|
+
const userName = useObservableValue(userName$, 'Guest'); // string
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<div>
|
|
149
|
+
<p>{`Doubled count: ${doubled}`}</p>
|
|
150
|
+
<p>{`Hello, ${userName}`}</p>
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
153
|
+
};
|
|
154
|
+
```
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type InitializedObservable } from 'synstate';
|
|
2
|
-
export declare const createBooleanState: (initialState: boolean) => readonly [useCurrentValue: () => boolean, Readonly<{
|
|
2
|
+
export declare const createBooleanState: (initialState: boolean) => readonly [useCurrentValue: () => boolean, utils: Readonly<{
|
|
3
3
|
state: InitializedObservable<boolean>;
|
|
4
4
|
setTrue: () => void;
|
|
5
5
|
setFalse: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-boolean-state.d.mts","sourceRoot":"","sources":["../src/create-boolean-state.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qBAAqB,EAE3B,MAAM,UAAU,CAAC;AAGlB,eAAO,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"create-boolean-state.d.mts","sourceRoot":"","sources":["../src/create-boolean-state.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qBAAqB,EAE3B,MAAM,UAAU,CAAC;AAGlB,eAAO,MAAM,kBAAkB,iBACf,OAAO,KACpB,SAAS,CACV,eAAe,EAAE,MAAM,OAAO,EAC9B,KAAK,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACtC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC;IACrC,MAAM,EAAE,MAAM,OAAO,CAAC;IACtB,WAAW,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,KAAK,OAAO,CAAC;IAC/D,UAAU,EAAE,MAAM,OAAO,CAAC;IAC1B,WAAW,EAAE,MAAM,OAAO,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC,CA+BH,CAAC"}
|
|
@@ -2,22 +2,33 @@ import { createBooleanState as createBooleanState$1 } from 'synstate';
|
|
|
2
2
|
import { useObservableValue } from './use-observable-value.mjs';
|
|
3
3
|
|
|
4
4
|
const createBooleanState = (initialState) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
5
|
+
const [
|
|
6
|
+
state,
|
|
7
|
+
{
|
|
8
|
+
setTrue,
|
|
9
|
+
setFalse,
|
|
10
|
+
setState,
|
|
11
|
+
toggle,
|
|
12
|
+
updateState,
|
|
13
|
+
resetState,
|
|
14
|
+
getSnapshot
|
|
15
|
+
}
|
|
16
|
+
] = createBooleanState$1(initialState);
|
|
17
|
+
const useCurrentValue = () => useObservableValue(state);
|
|
18
|
+
return [
|
|
19
|
+
useCurrentValue,
|
|
20
|
+
{
|
|
21
|
+
state,
|
|
22
|
+
setTrue,
|
|
23
|
+
setFalse,
|
|
24
|
+
setState,
|
|
25
|
+
toggle,
|
|
26
|
+
updateState,
|
|
27
|
+
resetState,
|
|
28
|
+
getSnapshot,
|
|
29
|
+
initialState
|
|
30
|
+
}
|
|
31
|
+
];
|
|
21
32
|
};
|
|
22
33
|
|
|
23
34
|
export { createBooleanState };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-boolean-state.mjs","sources":["../src/create-boolean-state.mts"],"sourcesContent":[
|
|
1
|
+
{"version":3,"file":"create-boolean-state.mjs","sources":["../src/create-boolean-state.mts"],"sourcesContent":["import {\n type InitializedObservable,\n createBooleanState as createBooleanStateBase,\n} from 'synstate';\nimport { useObservableValue } from './use-observable-value.mjs';\n\nexport const createBooleanState = (\n initialState: boolean,\n): readonly [\n useCurrentValue: () => boolean,\n utils: Readonly<{\n state: InitializedObservable<boolean>;\n setTrue: () => void;\n setFalse: () => void;\n setState: (next: boolean) => boolean;\n toggle: () => boolean;\n updateState: (updateFn: (prev: boolean) => boolean) => boolean;\n resetState: () => boolean;\n getSnapshot: () => boolean;\n initialState: boolean;\n }>,\n] => {\n const [\n state,\n {\n setTrue,\n setFalse,\n setState,\n toggle,\n updateState,\n resetState,\n getSnapshot,\n },\n ] = createBooleanStateBase(initialState);\n\n const useCurrentValue = (): boolean => useObservableValue(state);\n\n return [\n useCurrentValue,\n {\n state,\n setTrue,\n setFalse,\n setState,\n toggle,\n updateState,\n resetState,\n getSnapshot,\n initialState,\n },\n ] as const;\n};\n"],"names":["createBooleanStateBase"],"mappings":";;;AAMO,MAAM,kBAAA,GAAqB,CAChC,YAAA,KAcG;AACH,EAAA,MAAM;AAAA,IACJ,KAAA;AAAA,IACA;AAAA,MACE,OAAA;AAAA,MACA,QAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA;AAAA,MACA,WAAA;AAAA,MACA,UAAA;AAAA,MACA;AAAA;AACF,GACF,GAAIA,qBAAuB,YAAY,CAAA;AAEvC,EAAA,MAAM,eAAA,GAAkB,MAAe,kBAAA,CAAmB,KAAK,CAAA;AAE/D,EAAA,OAAO;AAAA,IACL,eAAA;AAAA,IACA;AAAA,MACE,KAAA;AAAA,MACA,OAAA;AAAA,MACA,QAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA;AAAA,MACA,WAAA;AAAA,MACA,UAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA;AACF,GACF;AACF;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type InitializedObservable } from 'synstate';
|
|
2
2
|
import { type Reducer } from 'ts-type-forge';
|
|
3
|
-
export declare const createReducer: <S, A>(reducer: Reducer<S, A>, initialState: S) => readonly [useCurrentValue: () => S, dispatch: (action: A) => S, Readonly<{
|
|
3
|
+
export declare const createReducer: <S, A>(reducer: Reducer<S, A>, initialState: S) => readonly [useCurrentValue: () => S, dispatch: (action: A) => S, utils: Readonly<{
|
|
4
4
|
state: InitializedObservable<S>;
|
|
5
5
|
getSnapshot: () => S;
|
|
6
6
|
initialState: S;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-reducer.d.mts","sourceRoot":"","sources":["../src/create-reducer.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C,eAAO,MAAM,aAAa,GAAI,CAAC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"create-reducer.d.mts","sourceRoot":"","sources":["../src/create-reducer.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C,eAAO,MAAM,aAAa,GAAI,CAAC,EAAE,CAAC,WACvB,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,gBACR,CAAC,KACd,SAAS,CACV,eAAe,EAAE,MAAM,CAAC,EACxB,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAC1B,KAAK,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC,CAAC;IACrB,YAAY,EAAE,CAAC,CAAC;CACjB,CAAC,CAUH,CAAC"}
|
package/dist/create-reducer.mjs
CHANGED
|
@@ -2,9 +2,12 @@ import { createReducer as createReducer$1 } from 'synstate';
|
|
|
2
2
|
import { useObservableValue } from './use-observable-value.mjs';
|
|
3
3
|
|
|
4
4
|
const createReducer = (reducer, initialState) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
const [state, dispatch, { getSnapshot }] = createReducer$1(
|
|
6
|
+
reducer,
|
|
7
|
+
initialState
|
|
8
|
+
);
|
|
9
|
+
const useCurrentValue = () => useObservableValue(state);
|
|
10
|
+
return [useCurrentValue, dispatch, { state, getSnapshot, initialState }];
|
|
8
11
|
};
|
|
9
12
|
|
|
10
13
|
export { createReducer };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-reducer.mjs","sources":["../src/create-reducer.mts"],"sourcesContent":[
|
|
1
|
+
{"version":3,"file":"create-reducer.mjs","sources":["../src/create-reducer.mts"],"sourcesContent":["import {\n createReducer as createReducerBase,\n type InitializedObservable,\n} from 'synstate';\nimport { type Reducer } from 'ts-type-forge';\nimport { useObservableValue } from './use-observable-value.mjs';\n\nexport const createReducer = <S, A>(\n reducer: Reducer<S, A>,\n initialState: S,\n): readonly [\n useCurrentValue: () => S,\n dispatch: (action: A) => S,\n utils: Readonly<{\n state: InitializedObservable<S>;\n getSnapshot: () => S;\n initialState: S;\n }>,\n] => {\n const [state, dispatch, { getSnapshot }] = createReducerBase(\n reducer,\n initialState,\n );\n\n const useCurrentValue = (): S => useObservableValue(state);\n\n return [useCurrentValue, dispatch, { state, getSnapshot, initialState }];\n};\n"],"names":["createReducerBase"],"mappings":";;;AAOO,MAAM,aAAA,GAAgB,CAC3B,OAAA,EACA,YAAA,KASG;AACH,EAAA,MAAM,CAAC,KAAA,EAAO,QAAA,EAAU,EAAE,WAAA,EAAa,CAAA,GAAIA,eAAA;AAAA,IACzC,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,eAAA,GAAkB,MAAS,kBAAA,CAAmB,KAAK,CAAA;AAEzD,EAAA,OAAO,CAAC,eAAA,EAAiB,QAAA,EAAU,EAAE,KAAA,EAAO,WAAA,EAAa,cAAc,CAAA;AACzE;;;;"}
|
package/dist/create-state.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type InitializedObservable } from 'synstate';
|
|
2
|
-
export declare const createState: <S>(initialState: S) => readonly [useCurrentValue: () => S, setState: (v: S) => S, Readonly<{
|
|
2
|
+
export declare const createState: <S>(initialState: S) => readonly [useCurrentValue: () => S, setState: (v: S) => S, utils: Readonly<{
|
|
3
3
|
state: InitializedObservable<S>;
|
|
4
4
|
updateState: (updateFn: (prev: S) => S) => S;
|
|
5
5
|
resetState: () => S;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-state.d.mts","sourceRoot":"","sources":["../src/create-state.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,UAAU,CAAC;AAGlB,eAAO,MAAM,WAAW,GAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"create-state.d.mts","sourceRoot":"","sources":["../src/create-state.mts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,UAAU,CAAC;AAGlB,eAAO,MAAM,WAAW,GAAI,CAAC,gBACb,CAAC,KACd,SAAS,CACV,eAAe,EAAE,MAAM,CAAC,EACxB,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EACrB,KAAK,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAChC,WAAW,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7C,UAAU,EAAE,MAAM,CAAC,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,CAAC;IACrB,YAAY,EAAE,CAAC,CAAC;CACjB,CAAC,CAkBH,CAAC"}
|
package/dist/create-state.mjs
CHANGED
|
@@ -2,19 +2,19 @@ import { createState as createState$1 } from 'synstate';
|
|
|
2
2
|
import { useObservableValue } from './use-observable-value.mjs';
|
|
3
3
|
|
|
4
4
|
const createState = (initialState) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
5
|
+
const [state, setState, { updateState, resetState, getSnapshot }] = createState$1(initialState);
|
|
6
|
+
const useCurrentValue = () => useObservableValue(state);
|
|
7
|
+
return [
|
|
8
|
+
useCurrentValue,
|
|
9
|
+
setState,
|
|
10
|
+
{
|
|
11
|
+
state,
|
|
12
|
+
updateState,
|
|
13
|
+
resetState,
|
|
14
|
+
getSnapshot,
|
|
15
|
+
initialState
|
|
16
|
+
}
|
|
17
|
+
];
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
export { createState };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-state.mjs","sources":["../src/create-state.mts"],"sourcesContent":[
|
|
1
|
+
{"version":3,"file":"create-state.mjs","sources":["../src/create-state.mts"],"sourcesContent":["import {\n createState as createStateBase,\n type InitializedObservable,\n} from 'synstate';\nimport { useObservableValue } from './use-observable-value.mjs';\n\nexport const createState = <S,>(\n initialState: S,\n): readonly [\n useCurrentValue: () => S,\n setState: (v: S) => S,\n utils: Readonly<{\n state: InitializedObservable<S>;\n updateState: (updateFn: (prev: S) => S) => S;\n resetState: () => S;\n getSnapshot: () => S;\n initialState: S;\n }>,\n] => {\n const [state, setState, { updateState, resetState, getSnapshot }] =\n createStateBase(initialState);\n\n const useCurrentValue = (): S => useObservableValue(state);\n\n return [\n useCurrentValue,\n setState,\n {\n state,\n updateState,\n resetState,\n getSnapshot,\n initialState,\n },\n ] as const;\n};\n"],"names":["createStateBase"],"mappings":";;;AAMO,MAAM,WAAA,GAAc,CACzB,YAAA,KAWG;AACH,EAAA,MAAM,CAAC,KAAA,EAAO,QAAA,EAAU,EAAE,WAAA,EAAa,YAAY,WAAA,EAAa,CAAA,GAC9DA,aAAA,CAAgB,YAAY,CAAA;AAE9B,EAAA,MAAM,eAAA,GAAkB,MAAS,kBAAA,CAAmB,KAAK,CAAA;AAEzD,EAAA,OAAO;AAAA,IACL,eAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,MACE,KAAA;AAAA,MACA,WAAA;AAAA,MACA,UAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA;AACF,GACF;AACF;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-observable-effect.d.mts","sourceRoot":"","sources":["../src/use-observable-effect.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,eAAO,MAAM,mBAAmB,GAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"use-observable-effect.d.mts","sourceRoot":"","sources":["../src/use-observable-effect.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,eAAO,MAAM,mBAAmB,GAAI,CAAC,eACtB,UAAU,CAAC,CAAC,CAAC,kBACV,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,KAC7B,IAQF,CAAC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
3
|
const useObservableEffect = (observable$, subscriptionFn) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
React.useEffect(() => {
|
|
5
|
+
const s = observable$.subscribe(subscriptionFn);
|
|
6
|
+
return () => {
|
|
7
|
+
s.unsubscribe();
|
|
8
|
+
};
|
|
9
|
+
}, []);
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
export { useObservableEffect };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-observable-effect.mjs","sources":["../src/use-observable-effect.mts"],"sourcesContent":[
|
|
1
|
+
{"version":3,"file":"use-observable-effect.mjs","sources":["../src/use-observable-effect.mts"],"sourcesContent":["import * as React from 'react';\nimport { type Observable } from 'synstate';\n\nexport const useObservableEffect = <A,>(\n observable$: Observable<A>,\n subscriptionFn: (v: A) => void,\n): void => {\n React.useEffect(() => {\n const s = observable$.subscribe(subscriptionFn);\n\n return () => {\n s.unsubscribe();\n };\n }, []);\n};\n"],"names":[],"mappings":";;AAGO,MAAM,mBAAA,GAAsB,CACjC,WAAA,EACA,cAAA,KACS;AACT,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,MAAM,CAAA,GAAI,WAAA,CAAY,SAAA,CAAU,cAAc,CAAA;AAE9C,IAAA,OAAO,MAAM;AACX,MAAA,CAAA,CAAE,WAAA,EAAY;AAAA,IAChB,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AACP;;;;"}
|
|
@@ -2,11 +2,14 @@ import * as React from 'react';
|
|
|
2
2
|
import { Optional } from 'ts-data-forge';
|
|
3
3
|
|
|
4
4
|
function useObservableValue(observable$, initialValue) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
const value = React.useSyncExternalStore(
|
|
6
|
+
(onStoreChange) => {
|
|
7
|
+
const { unsubscribe } = observable$.subscribe(onStoreChange);
|
|
8
|
+
return unsubscribe;
|
|
9
|
+
},
|
|
10
|
+
() => observable$.getSnapshot()
|
|
11
|
+
);
|
|
12
|
+
return Optional.unwrapOr(value, initialValue);
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
export { useObservableValue };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-observable-value.mjs","sources":["../src/use-observable-value.mts"],"sourcesContent":[
|
|
1
|
+
{"version":3,"file":"use-observable-value.mjs","sources":["../src/use-observable-value.mts"],"sourcesContent":["import * as React from 'react';\nimport { type InitializedObservable, type Observable } from 'synstate';\nimport { Optional } from 'ts-data-forge';\n\nexport function useObservableValue<A, B = A>(\n observable$: Observable<A>,\n initialValue: B,\n): A | B;\n\nexport function useObservableValue<A>(observable$: InitializedObservable<A>): A;\n\nexport function useObservableValue<A>(\n observable$: Observable<A>,\n): A | undefined;\n\nexport function useObservableValue<A, B = A>(\n observable$: Observable<A>,\n initialValue: B,\n): A | B;\n\nexport function useObservableValue<A, B = A>(\n observable$: Observable<A>,\n initialValue?: B,\n): A | B | undefined {\n const value = React.useSyncExternalStore(\n (onStoreChange: () => void) => {\n const { unsubscribe } = observable$.subscribe(onStoreChange);\n\n return unsubscribe;\n },\n () => observable$.getSnapshot(),\n );\n\n return Optional.unwrapOr(value, initialValue);\n}\n"],"names":[],"mappings":";;;AAoBO,SAAS,kBAAA,CACd,aACA,YAAA,EACmB;AACnB,EAAA,MAAM,QAAQ,KAAA,CAAM,oBAAA;AAAA,IAClB,CAAC,aAAA,KAA8B;AAC7B,MAAA,MAAM,EAAE,WAAA,EAAY,GAAI,WAAA,CAAY,UAAU,aAAa,CAAA;AAE3D,MAAA,OAAO,WAAA;AAAA,IACT,CAAA;AAAA,IACA,MAAM,YAAY,WAAA;AAAY,GAChC;AAEA,EAAA,OAAO,QAAA,CAAS,QAAA,CAAS,KAAA,EAAO,YAAY,CAAA;AAC9C;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-value-as-observable.d.mts","sourceRoot":"","sources":["../src/use-value-as-observable.mts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,UAAU,CAAC;AAElB,eAAO,MAAM,oBAAoB,GAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"use-value-as-observable.d.mts","sourceRoot":"","sources":["../src/use-value-as-observable.mts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,UAAU,CAAC;AAElB,eAAO,MAAM,oBAAoB,GAAI,CAAC,SAAU,CAAC,KAAG,UAAU,CAAC,CAAC,CA0B/D,CAAC"}
|
|
@@ -2,19 +2,25 @@ import * as React from 'react';
|
|
|
2
2
|
import { source, withInitialValue } from 'synstate';
|
|
3
3
|
|
|
4
4
|
const useValueAsObservable = (input) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
},
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
5
|
+
const sourceObservable = React.useMemo(source, []);
|
|
6
|
+
const state = React.useMemo(
|
|
7
|
+
() => sourceObservable.pipe(withInitialValue(input)),
|
|
8
|
+
[]
|
|
9
|
+
);
|
|
10
|
+
React.useEffect(
|
|
11
|
+
() => () => {
|
|
12
|
+
state.complete();
|
|
13
|
+
},
|
|
14
|
+
[]
|
|
15
|
+
);
|
|
16
|
+
const setState = React.useCallback((nextState) => {
|
|
17
|
+
sourceObservable.next(nextState);
|
|
18
|
+
return nextState;
|
|
19
|
+
}, []);
|
|
20
|
+
React.useEffect(() => {
|
|
21
|
+
setState(input);
|
|
22
|
+
}, [input]);
|
|
23
|
+
return state;
|
|
18
24
|
};
|
|
19
25
|
|
|
20
26
|
export { useValueAsObservable };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-value-as-observable.mjs","sources":["../src/use-value-as-observable.mts"],"sourcesContent":[
|
|
1
|
+
{"version":3,"file":"use-value-as-observable.mjs","sources":["../src/use-value-as-observable.mts"],"sourcesContent":["import * as React from 'react';\nimport {\n source,\n withInitialValue,\n type Observable,\n type SourceObservable,\n} from 'synstate';\n\nexport const useValueAsObservable = <A,>(input: A): Observable<A> => {\n const sourceObservable = React.useMemo<SourceObservable<A>>(source, []);\n\n const state = React.useMemo(\n () => sourceObservable.pipe(withInitialValue(input)),\n [],\n );\n\n React.useEffect(\n () => () => {\n state.complete();\n },\n [],\n );\n\n const setState = React.useCallback((nextState: A): A => {\n sourceObservable.next(nextState);\n\n return nextState;\n }, []);\n\n React.useEffect(() => {\n setState(input);\n }, [input]);\n\n return state;\n};\n"],"names":[],"mappings":";;;AAQO,MAAM,oBAAA,GAAuB,CAAK,KAAA,KAA4B;AACnE,EAAA,MAAM,gBAAA,GAAmB,KAAA,CAAM,OAAA,CAA6B,MAAA,EAAQ,EAAE,CAAA;AAEtE,EAAA,MAAM,QAAQ,KAAA,CAAM,OAAA;AAAA,IAClB,MAAM,gBAAA,CAAiB,IAAA,CAAK,gBAAA,CAAiB,KAAK,CAAC,CAAA;AAAA,IACnD;AAAC,GACH;AAEA,EAAA,KAAA,CAAM,SAAA;AAAA,IACJ,MAAM,MAAM;AACV,MAAA,KAAA,CAAM,QAAA,EAAS;AAAA,IACjB,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,WAAA,CAAY,CAAC,SAAA,KAAoB;AACtD,IAAA,gBAAA,CAAiB,KAAK,SAAS,CAAA;AAE/B,IAAA,OAAO,SAAA;AAAA,EACT,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,QAAA,CAAS,KAAK,CAAA;AAAA,EAChB,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAA,OAAO,KAAA;AACT;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "synstate-react-hooks",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Type-safe State Management Library for TypeScript/JavaScript",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
"LICENSE"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"ts-data-forge": "
|
|
31
|
-
"ts-type-forge": "
|
|
32
|
-
"synstate": "
|
|
30
|
+
"ts-data-forge": "^14.2.0",
|
|
31
|
+
"ts-type-forge": "^9.2.0",
|
|
32
|
+
"synstate": "2.0.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/argparse": "2.0.17",
|
|
36
|
-
"@types/react": "19.2.
|
|
37
|
-
"argparse": "
|
|
38
|
-
"react": "19.2.
|
|
36
|
+
"@types/react": "19.2.18",
|
|
37
|
+
"argparse": "3.0.0",
|
|
38
|
+
"react": "19.2.8"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"react": ">=18.0.0"
|
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
"doc": "run-s doc:embed doc:embed:jsdoc fmt",
|
|
50
50
|
"doc:embed": "tsx ./scripts/cmd/embed-examples.mts",
|
|
51
51
|
"doc:embed:jsdoc": "tsx ./scripts/cmd/embed-examples-in-jsdoc.mts",
|
|
52
|
-
"fmt": "format-uncommitted",
|
|
52
|
+
"fmt": "format-uncommitted --cwd .",
|
|
53
|
+
"fmt:diff": "format-diff-from origin/main --cwd .",
|
|
53
54
|
"fmt:full": "pnpm run z:prettier .",
|
|
54
55
|
"gen:re-export": "run-s gen:re-export:script fmt",
|
|
55
56
|
"gen:re-export:script": "tsx ./scripts/cmd/generate-re-export-script.mts",
|
|
@@ -63,10 +64,9 @@
|
|
|
63
64
|
"test:cov:ui": "vite preview --outDir ./coverage",
|
|
64
65
|
"test:ui": "pnpm run z:vitest:node --ui",
|
|
65
66
|
"testw": "pnpm run z:vitest:node watch",
|
|
66
|
-
"tsc": "tsc --noEmit",
|
|
67
|
-
"tscw": "tsc --noEmit --watch",
|
|
68
|
-
"type-check": "tsc --noEmit",
|
|
69
|
-
"update-packages": "pnpm update --latest",
|
|
67
|
+
"tsc": "node ../../node_modules/typescript-native/bin/tsc --noEmit",
|
|
68
|
+
"tscw": "node ../../node_modules/typescript-native/bin/tsc --noEmit --watch",
|
|
69
|
+
"type-check": "node ../../node_modules/typescript-native/bin/tsc --noEmit",
|
|
70
70
|
"z:prettier": "prettier --config ../../.prettierrc --ignore-path ../../.prettierignore --ignore-path ../../.gitignore --ignore-unknown --no-error-on-unmatched-pattern --write",
|
|
71
71
|
"z:vitest": "vitest --config ./configs/vitest.config.mts",
|
|
72
72
|
"z:vitest:node": "pnpm run z:vitest --project='Node.js'"
|
package/src/create-reducer.mts
CHANGED
package/src/create-state.mts
CHANGED