synstate-preact-hooks 6.1.1 → 6.2.1

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
@@ -1,6 +1,6 @@
1
1
  # SynState Preact hooks
2
2
 
3
- synstate-preact-hooks re-exports all exports from synstate except for `createState`, `createReducer`, and `createBooleanState`, and exports modified versions of those creation functions.
3
+ synstate-preact-hooks re-exports every function and type synstate exports except for `createState`, `createReducer`, and `createBooleanState`, and exports modified versions of those creation functions.
4
4
 
5
5
  The first element of the array returned by the `createState<T>` function provided by synstate-preact-hooks is changed from `InitializedObservable<T>` to a Preact hook `() => T`, and the `InitializedObservable<T>` has been moved to the `state` property in the object at index 2.
6
6
 
@@ -1,2 +1,3 @@
1
1
  export { attachIndex, audit, collectToArray, combine, combineLatest, counter, createAsyncChildObservable, createEventEmitter, createInitializedSyncChildObservable, createRootObservable, createScope, createSyncChildObservable, createValueEmitter, debounce, derive, distinctUntilChanged, empty, filter, flatMap, fromAbortablePromise, fromPromise, fromSubscribable, getCurrentScope, getKey, isChildObservable, isManagerObservable, isObservable, isRootObservable, just, keepEqualParts, map, mapOptional, mapResultErr, mapResultOk, mapTo, merge, mergeMap, onScopeDispose, pairwise, pluck, scan, skip, skipIfNoChange, skipUntil, skipWhile, source, switchMap, take, takeUntil, takeWhile, throttle, timer, untracked, unwrapOptional, unwrapResultErr, unwrapResultOk, withBuffered, withBufferedFrom, withCurrentValueFrom, withIndex, withInitialValue, withLatestFrom, zip, } from 'synstate';
2
+ export type { AsyncChildObservable, AsyncChildObservableHooks, AsyncChildObservableTools, AuditOperatorObservable, ChildObservable, ChildObservableConfig, ChildObservableKind, CombineObservable, CombineObservableRefined, CounterObservable, DebounceOperatorObservable, DeriveObservable, DeriveObservableRefined, DropInitialValueOperator, FilterOperatorObservable, FromPromiseObservable, FromSubscribableObservable, InitializedAsyncChildObservable, InitializedChildObservableConfig, InitializedObservable, InitializedRootObservable, InitializedSourceObservable, InitializedSyncChildObservable, KeepEqualPartsOperatorObservable, KeepInitialValueOperator, ManagerObservable, ManagerObservableKind, MapOperatorObservable, MergeMapOperatorObservable, MergeObservable, MergeObservableRefined, NonEmptyUnknownList, Observable, ObservableBase, ObservableKind, ObservableValue, Operator, PairwiseOperatorObservable, RootObservable, RootObservableConfig, RootObservableTools, ScanOperatorObservable, Scope, SkipIfNoChangeOperatorObservable, SkipUntilOperatorObservable, SkipWhileOperatorObservable, SourceObservable, StateOptions, Subscribable, Subscriber, Subscription, SwitchMapOperatorObservable, SyncChildObservable, SyncChildObservableHooks, SyncChildObservableTools, TakeOperatorObservable, TakeUntilOperatorObservable, TakeWhileOperatorObservable, ThrottleOperatorObservable, TimerId, TimerObservable, TupleToQueueTuple, Unwrap, UpdateToken, WithBufferedFromOperatorObservable, WithCurrentValueFromOperatorObservable, WithInitialValueOperator, WithInitialValueOperatorObservable, Wrap, WrapInitialized, ZipObservable, ZipObservableRefined, } from 'synstate';
2
3
  //# sourceMappingURL=synstate.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"synstate.d.mts","sourceRoot":"","sources":["../src/synstate.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,KAAK,EACL,cAAc,EACd,OAAO,EACP,aAAa,EACb,OAAO,EACP,0BAA0B,EAC1B,kBAAkB,EAClB,oCAAoC,EACpC,oBAAoB,EACpB,WAAW,EACX,yBAAyB,EACzB,kBAAkB,EAClB,QAAQ,EACR,MAAM,EACN,oBAAoB,EACpB,KAAK,EACL,MAAM,EACN,OAAO,EACP,oBAAoB,EACpB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,MAAM,EACN,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,IAAI,EACJ,cAAc,EACd,GAAG,EACH,WAAW,EACX,YAAY,EACZ,WAAW,EACX,KAAK,EACL,KAAK,EACL,QAAQ,EACR,cAAc,EACd,QAAQ,EACR,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,cAAc,EACd,SAAS,EACT,SAAS,EACT,MAAM,EACN,SAAS,EACT,IAAI,EACJ,SAAS,EACT,SAAS,EACT,QAAQ,EACR,KAAK,EACL,SAAS,EACT,cAAc,EACd,eAAe,EACf,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,EACpB,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,GAAG,GACJ,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"synstate.d.mts","sourceRoot":"","sources":["../src/synstate.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,KAAK,EACL,cAAc,EACd,OAAO,EACP,aAAa,EACb,OAAO,EACP,0BAA0B,EAC1B,kBAAkB,EAClB,oCAAoC,EACpC,oBAAoB,EACpB,WAAW,EACX,yBAAyB,EACzB,kBAAkB,EAClB,QAAQ,EACR,MAAM,EACN,oBAAoB,EACpB,KAAK,EACL,MAAM,EACN,OAAO,EACP,oBAAoB,EACpB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,MAAM,EACN,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,IAAI,EACJ,cAAc,EACd,GAAG,EACH,WAAW,EACX,YAAY,EACZ,WAAW,EACX,KAAK,EACL,KAAK,EACL,QAAQ,EACR,cAAc,EACd,QAAQ,EACR,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,cAAc,EACd,SAAS,EACT,SAAS,EACT,MAAM,EACN,SAAS,EACT,IAAI,EACJ,SAAS,EACT,SAAS,EACT,QAAQ,EACR,KAAK,EACL,SAAS,EACT,cAAc,EACd,eAAe,EACf,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,EACpB,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,GAAG,GACJ,MAAM,UAAU,CAAC;AAElB,YAAY,EACV,oBAAoB,EACpB,yBAAyB,EACzB,yBAAyB,EACzB,uBAAuB,EACvB,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,wBAAwB,EACxB,iBAAiB,EACjB,0BAA0B,EAC1B,gBAAgB,EAChB,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,qBAAqB,EACrB,0BAA0B,EAC1B,+BAA+B,EAC/B,gCAAgC,EAChC,qBAAqB,EACrB,yBAAyB,EACzB,2BAA2B,EAC3B,8BAA8B,EAC9B,gCAAgC,EAChC,wBAAwB,EACxB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,0BAA0B,EAC1B,eAAe,EACf,sBAAsB,EACtB,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,cAAc,EACd,eAAe,EACf,QAAQ,EACR,0BAA0B,EAC1B,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,EACL,gCAAgC,EAChC,2BAA2B,EAC3B,2BAA2B,EAC3B,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,2BAA2B,EAC3B,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,2BAA2B,EAC3B,2BAA2B,EAC3B,0BAA0B,EAC1B,OAAO,EACP,eAAe,EACf,iBAAiB,EACjB,MAAM,EACN,WAAW,EACX,kCAAkC,EAClC,sCAAsC,EACtC,wBAAwB,EACxB,kCAAkC,EAClC,IAAI,EACJ,eAAe,EACf,aAAa,EACb,oBAAoB,GACrB,MAAM,UAAU,CAAC"}
@@ -1,3 +1,17 @@
1
1
  import type { Observable } from 'synstate';
2
+ /**
3
+ * Subscribes `subscriptionFn` to `observable$` while the component is mounted,
4
+ * and unsubscribes when it unmounts.
5
+ *
6
+ * Each value is passed to the `subscriptionFn` of the latest render, so it sees
7
+ * the current props and state; a new function on every render does not
8
+ * re-subscribe. Passing a different Observable moves the subscription to it,
9
+ * so pass one that keeps its identity across renders (made outside the
10
+ * component, or memoized): one built during render is subscribed again, and an
11
+ * initialized one calls `subscriptionFn` again, on every render.
12
+ *
13
+ * @param observable$ The Observable to subscribe to.
14
+ * @param subscriptionFn Called with each value `observable$` emits.
15
+ */
2
16
  export declare const useObservableEffect: <A>(observable$: Observable<A>, subscriptionFn: (v: A) => void) => void;
3
17
  //# sourceMappingURL=use-observable-effect.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-observable-effect.d.mts","sourceRoot":"","sources":["../src/use-observable-effect.mts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,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
+ {"version":3,"file":"use-observable-effect.d.mts","sourceRoot":"","sources":["../src/use-observable-effect.mts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,GAAI,CAAC,eACtB,UAAU,CAAC,CAAC,CAAC,kBACV,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,KAC7B,IAiBF,CAAC"}
@@ -1,10 +1,31 @@
1
1
  import * as Preact from 'preact/hooks';
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
2
16
  export const useObservableEffect = (observable$, subscriptionFn) => {
17
+ const mut_subscriptionFnRef = Preact.useRef(subscriptionFn);
18
+
19
+
20
+
21
+ mut_subscriptionFnRef.current = subscriptionFn;
3
22
  Preact.useEffect(() => {
4
- const s = observable$.subscribe(subscriptionFn);
23
+ const s = observable$.subscribe((v) => {
24
+ mut_subscriptionFnRef.current(v);
25
+ });
5
26
  return () => {
6
27
  s.unsubscribe();
7
28
  };
8
- }, []);
29
+ }, [observable$]);
9
30
  };
10
31
  //# sourceMappingURL=use-observable-effect.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-observable-effect.mjs","sourceRoot":"","sources":["../src/use-observable-effect.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AAGvC,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,WAA0B,EAC1B,cAA8B,EACxB,EAAE;IACR,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,MAAM,CAAC,GAAG,WAAW,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QAEhD,OAAO,GAAG,EAAE;YACV,CAAC,CAAC,WAAW,EAAE,CAAC;QAClB,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;AACT,CAAC,CAAC"}
1
+ {"version":3,"file":"use-observable-effect.mjs","sourceRoot":"","sources":["../src/use-observable-effect.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AAGvC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,WAA0B,EAC1B,cAA8B,EACxB,EAAE;IACR,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAE5D,6EAA6E;IAC7E,6EAA6E;IAC7E,2EAA2E;IAC3E,qBAAqB,CAAC,OAAO,GAAG,cAAc,CAAC;IAE/C,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,MAAM,CAAC,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE;YACpC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,CAAC,CAAC,WAAW,EAAE,CAAC;QAClB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC"}
@@ -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,SAAU,CAAC,KAAG,UAAU,CAAC,CAAC,CA2B/D,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,CAwB/D,CAAC"}
@@ -8,12 +8,11 @@ export const useValueAsObservable = (input) => {
8
8
  () => () => {
9
9
  state.complete();
10
10
  }, []);
11
- const setState = Preact.useCallback((nextState) => {
12
- sourceObservable.next(nextState);
13
- return nextState;
14
- }, []);
15
11
  Preact.useEffect(() => {
16
- setState(input);
12
+
13
+ if (!Object.is(state.getSnapshot().value, input)) {
14
+ sourceObservable.next(input);
15
+ }
17
16
  }, [input]);
18
17
  return state;
19
18
  };
@@ -1 +1 @@
1
- {"version":3,"file":"use-value-as-observable.mjs","sourceRoot":"","sources":["../src/use-value-as-observable.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,EACL,MAAM,EACN,gBAAgB,GAGjB,MAAM,UAAU,CAAC;AAElB,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAK,KAAQ,EAAiB,EAAE;IAClE,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAsB,MAAM,EAAE,EAAE,CAAC,CAAC;IAEzE,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAC1B,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,EACpD,EAAE,CACH,CAAC;IAEF,MAAM,CAAC,SAAS;IACd,+DAA+D;IAC/D,GAAG,EAAE,CAAC,GAAG,EAAE;QACT,KAAK,CAAC,QAAQ,EAAE,CAAC;IACnB,CAAC,EACD,EAAE,CACH,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,SAAY,EAAK,EAAE;QACtD,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEjC,OAAO,SAAS,CAAC;IACnB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
1
+ {"version":3,"file":"use-value-as-observable.mjs","sourceRoot":"","sources":["../src/use-value-as-observable.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,EACL,MAAM,EACN,gBAAgB,GAGjB,MAAM,UAAU,CAAC;AAElB,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAK,KAAQ,EAAiB,EAAE;IAClE,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAsB,MAAM,EAAE,EAAE,CAAC,CAAC;IAEzE,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAC1B,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,EACpD,EAAE,CACH,CAAC;IAEF,MAAM,CAAC,SAAS;IACd,+DAA+D;IAC/D,GAAG,EAAE,CAAC,GAAG,EAAE;QACT,KAAK,CAAC,QAAQ,EAAE,CAAC;IACnB,CAAC,EACD,EAAE,CACH,CAAC;IAEF,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,8DAA8D;QAC9D,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;YACjD,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synstate-preact-hooks",
3
- "version": "6.1.1",
3
+ "version": "6.2.1",
4
4
  "description": "Type-safe State Management Library for TypeScript/JavaScript",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,18 +28,18 @@
28
28
  "LICENSE"
29
29
  ],
30
30
  "dependencies": {
31
- "synstate": "6.1.1",
32
- "ts-data-forge": "^14.10.0",
31
+ "synstate": "6.2.1",
32
+ "ts-data-forge": "^14.10.2",
33
33
  "ts-type-forge": "^9.2.2"
34
34
  },
35
35
  "devDependencies": {
36
- "@sumi-lang/cli": "0.1.3",
36
+ "@sumi-lang/cli": "0.1.5",
37
37
  "@testing-library/preact": "3.2.4",
38
38
  "@vitest/browser-playwright": "5.0.5",
39
- "eslint-config-typed": "7.1.0",
40
- "eslint-plugin-ts-data-forge": "0.10.5",
41
- "eslint-plugin-ts-fortress": "1.3.10",
42
- "eslint-plugin-ts-type-forge": "0.8.15",
39
+ "eslint-config-typed": "7.3.1",
40
+ "eslint-plugin-ts-data-forge": "0.10.8",
41
+ "eslint-plugin-ts-fortress": "1.3.12",
42
+ "eslint-plugin-ts-type-forge": "0.8.17",
43
43
  "playwright": "1.64.1",
44
44
  "preact": "10.29.8",
45
45
  "prettier": "3.9.10",
package/src/synstate.mts CHANGED
@@ -63,3 +63,78 @@ export {
63
63
  withLatestFrom,
64
64
  zip,
65
65
  } from 'synstate';
66
+
67
+ export type {
68
+ AsyncChildObservable,
69
+ AsyncChildObservableHooks,
70
+ AsyncChildObservableTools,
71
+ AuditOperatorObservable,
72
+ ChildObservable,
73
+ ChildObservableConfig,
74
+ ChildObservableKind,
75
+ CombineObservable,
76
+ CombineObservableRefined,
77
+ CounterObservable,
78
+ DebounceOperatorObservable,
79
+ DeriveObservable,
80
+ DeriveObservableRefined,
81
+ DropInitialValueOperator,
82
+ FilterOperatorObservable,
83
+ FromPromiseObservable,
84
+ FromSubscribableObservable,
85
+ InitializedAsyncChildObservable,
86
+ InitializedChildObservableConfig,
87
+ InitializedObservable,
88
+ InitializedRootObservable,
89
+ InitializedSourceObservable,
90
+ InitializedSyncChildObservable,
91
+ KeepEqualPartsOperatorObservable,
92
+ KeepInitialValueOperator,
93
+ ManagerObservable,
94
+ ManagerObservableKind,
95
+ MapOperatorObservable,
96
+ MergeMapOperatorObservable,
97
+ MergeObservable,
98
+ MergeObservableRefined,
99
+ NonEmptyUnknownList,
100
+ Observable,
101
+ ObservableBase,
102
+ ObservableKind,
103
+ ObservableValue,
104
+ Operator,
105
+ PairwiseOperatorObservable,
106
+ RootObservable,
107
+ RootObservableConfig,
108
+ RootObservableTools,
109
+ ScanOperatorObservable,
110
+ Scope,
111
+ SkipIfNoChangeOperatorObservable,
112
+ SkipUntilOperatorObservable,
113
+ SkipWhileOperatorObservable,
114
+ SourceObservable,
115
+ StateOptions,
116
+ Subscribable,
117
+ Subscriber,
118
+ Subscription,
119
+ SwitchMapOperatorObservable,
120
+ SyncChildObservable,
121
+ SyncChildObservableHooks,
122
+ SyncChildObservableTools,
123
+ TakeOperatorObservable,
124
+ TakeUntilOperatorObservable,
125
+ TakeWhileOperatorObservable,
126
+ ThrottleOperatorObservable,
127
+ TimerId,
128
+ TimerObservable,
129
+ TupleToQueueTuple,
130
+ Unwrap,
131
+ UpdateToken,
132
+ WithBufferedFromOperatorObservable,
133
+ WithCurrentValueFromOperatorObservable,
134
+ WithInitialValueOperator,
135
+ WithInitialValueOperatorObservable,
136
+ Wrap,
137
+ WrapInitialized,
138
+ ZipObservable,
139
+ ZipObservableRefined,
140
+ } from 'synstate';
@@ -1,15 +1,38 @@
1
1
  import * as Preact from 'preact/hooks';
2
2
  import type { Observable } from 'synstate';
3
3
 
4
+ /**
5
+ * Subscribes `subscriptionFn` to `observable$` while the component is mounted,
6
+ * and unsubscribes when it unmounts.
7
+ *
8
+ * Each value is passed to the `subscriptionFn` of the latest render, so it sees
9
+ * the current props and state; a new function on every render does not
10
+ * re-subscribe. Passing a different Observable moves the subscription to it,
11
+ * so pass one that keeps its identity across renders (made outside the
12
+ * component, or memoized): one built during render is subscribed again, and an
13
+ * initialized one calls `subscriptionFn` again, on every render.
14
+ *
15
+ * @param observable$ The Observable to subscribe to.
16
+ * @param subscriptionFn Called with each value `observable$` emits.
17
+ */
4
18
  export const useObservableEffect = <A,>(
5
19
  observable$: Observable<A>,
6
20
  subscriptionFn: (v: A) => void,
7
21
  ): void => {
22
+ const mut_subscriptionFnRef = Preact.useRef(subscriptionFn);
23
+
24
+ // Stored as the component renders, before any effect of the commit can emit.
25
+ // Preact has no concurrent rendering; only a render that throws (to an error
26
+ // boundary, or to suspend) leaves its function here until the next render.
27
+ mut_subscriptionFnRef.current = subscriptionFn;
28
+
8
29
  Preact.useEffect(() => {
9
- const s = observable$.subscribe(subscriptionFn);
30
+ const s = observable$.subscribe((v) => {
31
+ mut_subscriptionFnRef.current(v);
32
+ });
10
33
 
11
34
  return () => {
12
35
  s.unsubscribe();
13
36
  };
14
- }, []);
37
+ }, [observable$]);
15
38
  };
@@ -22,14 +22,11 @@ export const useValueAsObservable = <A,>(input: A): Observable<A> => {
22
22
  [],
23
23
  );
24
24
 
25
- const setState = Preact.useCallback((nextState: A): A => {
26
- sourceObservable.next(nextState);
27
-
28
- return nextState;
29
- }, []);
30
-
31
25
  Preact.useEffect(() => {
32
- setState(input);
26
+ // The observable already holds the value it was created with.
27
+ if (!Object.is(state.getSnapshot().value, input)) {
28
+ sourceObservable.next(input);
29
+ }
33
30
  }, [input]);
34
31
 
35
32
  return state;