react-rx 3.0.0-4 → 3.0.0-6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/dist/index.d.mts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +54 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +25 -23
- package/src/__tests__/strictmode.test.ts +1 -0
- package/src/__tests__/useObservable.test.tsx +1 -0
- package/src/useObservable.ts +9 -10
- package/src/useObservableEvent.ts +4 -29
- package/dist/cjs/__tests__/strictmode.test.d.ts +0 -1
- package/dist/cjs/__tests__/strictmode.test.js +0 -96
- package/dist/cjs/__tests__/useObservable.test.d.ts +0 -1
- package/dist/cjs/__tests__/useObservable.test.js +0 -116
- package/dist/cjs/index.d.ts +0 -2
- package/dist/cjs/index.js +0 -18
- package/dist/cjs/useObservable.d.ts +0 -4
- package/dist/cjs/useObservable.js +0 -48
- package/dist/cjs/useObservableEvent.d.ts +0 -8
- package/dist/cjs/useObservableEvent.js +0 -52
- package/dist/es2015/__tests__/strictmode.test.d.ts +0 -1
- package/dist/es2015/__tests__/strictmode.test.js +0 -58
- package/dist/es2015/__tests__/useObservable.test.d.ts +0 -1
- package/dist/es2015/__tests__/useObservable.test.js +0 -110
- package/dist/es2015/index.d.ts +0 -2
- package/dist/es2015/index.js +0 -2
- package/dist/es2015/useObservable.d.ts +0 -4
- package/dist/es2015/useObservable.js +0 -44
- package/dist/es2015/useObservableEvent.d.ts +0 -8
- package/dist/es2015/useObservableEvent.js +0 -41
- package/dist/esm/__tests__/strictmode.test.d.ts +0 -1
- package/dist/esm/__tests__/strictmode.test.js +0 -94
- package/dist/esm/__tests__/useObservable.test.d.ts +0 -1
- package/dist/esm/__tests__/useObservable.test.js +0 -114
- package/dist/esm/index.d.ts +0 -2
- package/dist/esm/index.js +0 -2
- package/dist/esm/useObservable.d.ts +0 -4
- package/dist/esm/useObservable.js +0 -44
- package/dist/esm/useObservableEvent.d.ts +0 -8
- package/dist/esm/useObservableEvent.js +0 -46
package/LICENSE
CHANGED
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {Observable} from 'rxjs'
|
|
2
|
+
import type {ObservedValueOf} from 'rxjs'
|
|
3
|
+
|
|
4
|
+
/** @public */
|
|
5
|
+
export declare function useObservable<ObservableType extends Observable<any>>(
|
|
6
|
+
observable: ObservableType,
|
|
7
|
+
initialValue?: ObservedValueOf<ObservableType> | (() => ObservedValueOf<ObservableType>),
|
|
8
|
+
): ObservedValueOf<ObservableType>
|
|
9
|
+
|
|
10
|
+
/** @public */
|
|
11
|
+
export declare function useObservableEvent<T, U>(
|
|
12
|
+
fn: (arg: Observable<T>) => Observable<U>,
|
|
13
|
+
): (arg: T) => void
|
|
14
|
+
|
|
15
|
+
export {}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {Observable} from 'rxjs'
|
|
2
|
+
import type {ObservedValueOf} from 'rxjs'
|
|
3
|
+
|
|
4
|
+
/** @public */
|
|
5
|
+
export declare function useObservable<ObservableType extends Observable<any>>(
|
|
6
|
+
observable: ObservableType,
|
|
7
|
+
initialValue?: ObservedValueOf<ObservableType> | (() => ObservedValueOf<ObservableType>),
|
|
8
|
+
): ObservedValueOf<ObservableType>
|
|
9
|
+
|
|
10
|
+
/** @public */
|
|
11
|
+
export declare function useObservableEvent<T, U>(
|
|
12
|
+
fn: (arg: Observable<T>) => Observable<U>,
|
|
13
|
+
): (arg: T) => void
|
|
14
|
+
|
|
15
|
+
export {}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: !0 });
|
|
3
|
+
var react = require("react"), operators = require("rxjs/operators"), observableCallback = require("observable-callback");
|
|
4
|
+
function getValue(value) {
|
|
5
|
+
return typeof value == "function" ? value() : value;
|
|
6
|
+
}
|
|
7
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
function useObservable(observable, initialValue) {
|
|
9
|
+
const initialValueRef = react.useRef(getValue(initialValue));
|
|
10
|
+
react.useEffect(() => {
|
|
11
|
+
initialValueRef.current = getValue(initialValue);
|
|
12
|
+
}, [initialValue]);
|
|
13
|
+
const store = react.useMemo(() => {
|
|
14
|
+
if (!cache.has(observable)) {
|
|
15
|
+
const entry = {
|
|
16
|
+
snapshot: initialValueRef.current
|
|
17
|
+
};
|
|
18
|
+
entry.observable = observable.pipe(
|
|
19
|
+
operators.shareReplay({ refCount: !0, bufferSize: 1 }),
|
|
20
|
+
operators.tap((value) => entry.snapshot = value)
|
|
21
|
+
), entry.subscription = entry.observable.subscribe(), cache.set(observable, entry);
|
|
22
|
+
}
|
|
23
|
+
const instance = cache.get(observable);
|
|
24
|
+
return instance.subscription.closed && (instance.subscription = instance.observable.subscribe()), {
|
|
25
|
+
subscribe: (onStoreChange) => {
|
|
26
|
+
const subscription = instance.observable.subscribe(onStoreChange);
|
|
27
|
+
return instance.subscription.unsubscribe(), () => subscription.unsubscribe();
|
|
28
|
+
},
|
|
29
|
+
getSnapshot: () => instance.snapshot
|
|
30
|
+
};
|
|
31
|
+
}, [observable]);
|
|
32
|
+
return react.useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
33
|
+
}
|
|
34
|
+
function useObservableEvent(fn) {
|
|
35
|
+
const [[calls$, call]] = react.useState(() => observableCallback.observableCallback()), callback = useEffectEvent(fn);
|
|
36
|
+
return react.useEffect(() => {
|
|
37
|
+
const subscription = calls$.pipe(callback).subscribe();
|
|
38
|
+
return () => subscription.unsubscribe();
|
|
39
|
+
}, [callback, calls$]), call;
|
|
40
|
+
}
|
|
41
|
+
function useEffectEvent(fn) {
|
|
42
|
+
const ref = react.useRef(null);
|
|
43
|
+
return react.useInsertionEffect(() => {
|
|
44
|
+
ref.current = fn;
|
|
45
|
+
}, [fn]), react.useCallback((...args) => {
|
|
46
|
+
const f = ref.current;
|
|
47
|
+
return f(...args);
|
|
48
|
+
}, []);
|
|
49
|
+
}
|
|
50
|
+
exports.useObservable = useObservable;
|
|
51
|
+
exports.useObservableEvent = useObservableEvent;
|
|
52
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/useObservable.ts","../src/useObservableEvent.ts"],"sourcesContent":["import {useEffect, useMemo, useRef, useSyncExternalStore} from 'react'\nimport type {Observable, ObservedValueOf, Subscription} from 'rxjs'\nimport {shareReplay, tap} from 'rxjs/operators'\n\nfunction getValue<T>(value: T): T extends () => infer U ? U : T {\n return typeof value === 'function' ? value() : value\n}\ninterface CacheRecord<T> {\n subscription: Subscription\n observable: Observable<T>\n snapshot: T\n}\n\nconst cache = new WeakMap<Observable<any>, CacheRecord<any>>()\n\n/** @public */\nexport function useObservable<ObservableType extends Observable<any>>(\n observable: ObservableType,\n initialValue?: ObservedValueOf<ObservableType> | (() => ObservedValueOf<ObservableType>),\n): ObservedValueOf<ObservableType> {\n /**\n * Store the initialValue in a ref, as we don't want a changed `initialValue` to trigger a re-subscription.\n * But we also don't want the initialValue to be stale if the observable changes.\n */\n const initialValueRef = useRef(getValue(initialValue) as ObservedValueOf<ObservableType>)\n\n /**\n * Ensures that the initialValue is always up-to-date in case the observable changes.\n */\n useEffect(() => {\n initialValueRef.current = getValue(initialValue) as ObservedValueOf<ObservableType>\n }, [initialValue])\n\n const store = useMemo(() => {\n if (!cache.has(observable)) {\n const entry: Partial<CacheRecord<ObservedValueOf<ObservableType>>> = {\n snapshot: initialValueRef.current,\n }\n entry.observable = observable.pipe(\n shareReplay({refCount: true, bufferSize: 1}),\n tap((value) => (entry.snapshot = value)),\n )\n\n // Eagerly subscribe to sync set `entry.currentValue` to what the observable returns, and keep the observable alive until the component unmounts.\n entry.subscription = entry.observable.subscribe()\n\n cache.set(observable, entry as CacheRecord<ObservedValueOf<ObservableType>>)\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const instance = cache.get(observable)!\n if (instance.subscription.closed) {\n instance.subscription = instance.observable.subscribe()\n }\n\n return {\n subscribe: (onStoreChange: () => void) => {\n const subscription = instance.observable.subscribe(onStoreChange)\n instance.subscription.unsubscribe()\n return () => subscription.unsubscribe()\n },\n getSnapshot: () => instance.snapshot,\n }\n }, [observable])\n\n return useSyncExternalStore<ObservedValueOf<ObservableType>>(store.subscribe, store.getSnapshot)\n}\n","import {observableCallback} from 'observable-callback'\nimport {useCallback, useEffect, useInsertionEffect, useRef, useState} from 'react'\nimport {type Observable} from 'rxjs'\n\n/** @public */\nexport function useObservableEvent<T, U>(\n fn: (arg: Observable<T>) => Observable<U>,\n): (arg: T) => void {\n const [[calls$, call]] = useState(() => observableCallback<T>())\n\n const callback = useEffectEvent(fn)\n\n useEffect(() => {\n const subscription = calls$.pipe(callback).subscribe()\n return () => subscription.unsubscribe()\n }, [callback, calls$])\n\n return call\n}\n\n/**\n * This is a ponyfill of the upcoming `useEffectEvent` hook that'll arrive in React 19\n */\nfunction useEffectEvent<\n const T extends (\n ...args: // eslint-disable-next-line @typescript-eslint/no-explicit-any\n any[]\n ) => void,\n>(fn: T): T {\n const ref = useRef<T | null>(null)\n useInsertionEffect(() => {\n ref.current = fn\n }, [fn])\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return useCallback((...args: any[]) => {\n const f = ref.current!\n return f(...args)\n }, []) as T\n}\n"],"names":["useRef","useEffect","useMemo","shareReplay","tap","useSyncExternalStore","useState","observableCallback","useInsertionEffect","useCallback"],"mappings":";;;AAIA,SAAS,SAAY,OAA2C;AAC9D,SAAO,OAAO,SAAU,aAAa,MAAA,IAAU;AACjD;AAOA,MAAM,4BAAY;AAGF,SAAA,cACd,YACA,cACiC;AAKjC,QAAM,kBAAkBA,MAAA,OAAO,SAAS,YAAY,CAAoC;AAKxFC,QAAAA,UAAU,MAAM;AACE,oBAAA,UAAU,SAAS,YAAY;AAAA,EAAA,GAC9C,CAAC,YAAY,CAAC;AAEX,QAAA,QAAQC,MAAAA,QAAQ,MAAM;AAC1B,QAAI,CAAC,MAAM,IAAI,UAAU,GAAG;AAC1B,YAAM,QAA+D;AAAA,QACnE,UAAU,gBAAgB;AAAA,MAAA;AAE5B,YAAM,aAAa,WAAW;AAAA,QAC5BC,sBAAY,EAAC,UAAU,IAAM,YAAY,GAAE;AAAA,QAC3CC,UAAAA,IAAI,CAAC,UAAW,MAAM,WAAW,KAAM;AAAA,MACzC,GAGA,MAAM,eAAe,MAAM,WAAW,aAEtC,MAAM,IAAI,YAAY,KAAqD;AAAA,IAC7E;AAEM,UAAA,WAAW,MAAM,IAAI,UAAU;AACjC,WAAA,SAAS,aAAa,WACxB,SAAS,eAAe,SAAS,WAAW,cAGvC;AAAA,MACL,WAAW,CAAC,kBAA8B;AACxC,cAAM,eAAe,SAAS,WAAW,UAAU,aAAa;AAChE,eAAA,SAAS,aAAa,YACf,GAAA,MAAM,aAAa;MAC5B;AAAA,MACA,aAAa,MAAM,SAAS;AAAA,IAAA;AAAA,EAC9B,GACC,CAAC,UAAU,CAAC;AAEf,SAAOC,MAAsD,qBAAA,MAAM,WAAW,MAAM,WAAW;AACjG;AC5DO,SAAS,mBACd,IACkB;AAClB,QAAM,CAAC,CAAC,QAAQ,IAAI,CAAC,IAAIC,MAAS,SAAA,MAAMC,mBAAsB,mBAAA,CAAC,GAEzD,WAAW,eAAe,EAAE;AAElC,SAAAN,MAAA,UAAU,MAAM;AACd,UAAM,eAAe,OAAO,KAAK,QAAQ,EAAE,UAAU;AAC9C,WAAA,MAAM,aAAa;EACzB,GAAA,CAAC,UAAU,MAAM,CAAC,GAEd;AACT;AAKA,SAAS,eAKP,IAAU;AACJ,QAAA,MAAMD,aAAiB,IAAI;AACjC,SAAAQ,MAAA,mBAAmB,MAAM;AACvB,QAAI,UAAU;AAAA,KACb,CAAC,EAAE,CAAC,GAEAC,MAAAA,YAAY,IAAI,SAAgB;AACrC,UAAM,IAAI,IAAI;AACP,WAAA,EAAE,GAAG,IAAI;AAAA,EAClB,GAAG,CAAE,CAAA;AACP;;;"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useRef, useEffect, useMemo, useSyncExternalStore, useState, useInsertionEffect, useCallback } from "react";
|
|
2
|
+
import { shareReplay, tap } from "rxjs/operators";
|
|
3
|
+
import { observableCallback } from "observable-callback";
|
|
4
|
+
function getValue(value) {
|
|
5
|
+
return typeof value == "function" ? value() : value;
|
|
6
|
+
}
|
|
7
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
function useObservable(observable, initialValue) {
|
|
9
|
+
const initialValueRef = useRef(getValue(initialValue));
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
initialValueRef.current = getValue(initialValue);
|
|
12
|
+
}, [initialValue]);
|
|
13
|
+
const store = useMemo(() => {
|
|
14
|
+
if (!cache.has(observable)) {
|
|
15
|
+
const entry = {
|
|
16
|
+
snapshot: initialValueRef.current
|
|
17
|
+
};
|
|
18
|
+
entry.observable = observable.pipe(
|
|
19
|
+
shareReplay({ refCount: !0, bufferSize: 1 }),
|
|
20
|
+
tap((value) => entry.snapshot = value)
|
|
21
|
+
), entry.subscription = entry.observable.subscribe(), cache.set(observable, entry);
|
|
22
|
+
}
|
|
23
|
+
const instance = cache.get(observable);
|
|
24
|
+
return instance.subscription.closed && (instance.subscription = instance.observable.subscribe()), {
|
|
25
|
+
subscribe: (onStoreChange) => {
|
|
26
|
+
const subscription = instance.observable.subscribe(onStoreChange);
|
|
27
|
+
return instance.subscription.unsubscribe(), () => subscription.unsubscribe();
|
|
28
|
+
},
|
|
29
|
+
getSnapshot: () => instance.snapshot
|
|
30
|
+
};
|
|
31
|
+
}, [observable]);
|
|
32
|
+
return useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
33
|
+
}
|
|
34
|
+
function useObservableEvent(fn) {
|
|
35
|
+
const [[calls$, call]] = useState(() => observableCallback()), callback = useEffectEvent(fn);
|
|
36
|
+
return useEffect(() => {
|
|
37
|
+
const subscription = calls$.pipe(callback).subscribe();
|
|
38
|
+
return () => subscription.unsubscribe();
|
|
39
|
+
}, [callback, calls$]), call;
|
|
40
|
+
}
|
|
41
|
+
function useEffectEvent(fn) {
|
|
42
|
+
const ref = useRef(null);
|
|
43
|
+
return useInsertionEffect(() => {
|
|
44
|
+
ref.current = fn;
|
|
45
|
+
}, [fn]), useCallback((...args) => {
|
|
46
|
+
const f = ref.current;
|
|
47
|
+
return f(...args);
|
|
48
|
+
}, []);
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
useObservable,
|
|
52
|
+
useObservableEvent
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/useObservable.ts","../src/useObservableEvent.ts"],"sourcesContent":["import {useEffect, useMemo, useRef, useSyncExternalStore} from 'react'\nimport type {Observable, ObservedValueOf, Subscription} from 'rxjs'\nimport {shareReplay, tap} from 'rxjs/operators'\n\nfunction getValue<T>(value: T): T extends () => infer U ? U : T {\n return typeof value === 'function' ? value() : value\n}\ninterface CacheRecord<T> {\n subscription: Subscription\n observable: Observable<T>\n snapshot: T\n}\n\nconst cache = new WeakMap<Observable<any>, CacheRecord<any>>()\n\n/** @public */\nexport function useObservable<ObservableType extends Observable<any>>(\n observable: ObservableType,\n initialValue?: ObservedValueOf<ObservableType> | (() => ObservedValueOf<ObservableType>),\n): ObservedValueOf<ObservableType> {\n /**\n * Store the initialValue in a ref, as we don't want a changed `initialValue` to trigger a re-subscription.\n * But we also don't want the initialValue to be stale if the observable changes.\n */\n const initialValueRef = useRef(getValue(initialValue) as ObservedValueOf<ObservableType>)\n\n /**\n * Ensures that the initialValue is always up-to-date in case the observable changes.\n */\n useEffect(() => {\n initialValueRef.current = getValue(initialValue) as ObservedValueOf<ObservableType>\n }, [initialValue])\n\n const store = useMemo(() => {\n if (!cache.has(observable)) {\n const entry: Partial<CacheRecord<ObservedValueOf<ObservableType>>> = {\n snapshot: initialValueRef.current,\n }\n entry.observable = observable.pipe(\n shareReplay({refCount: true, bufferSize: 1}),\n tap((value) => (entry.snapshot = value)),\n )\n\n // Eagerly subscribe to sync set `entry.currentValue` to what the observable returns, and keep the observable alive until the component unmounts.\n entry.subscription = entry.observable.subscribe()\n\n cache.set(observable, entry as CacheRecord<ObservedValueOf<ObservableType>>)\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const instance = cache.get(observable)!\n if (instance.subscription.closed) {\n instance.subscription = instance.observable.subscribe()\n }\n\n return {\n subscribe: (onStoreChange: () => void) => {\n const subscription = instance.observable.subscribe(onStoreChange)\n instance.subscription.unsubscribe()\n return () => subscription.unsubscribe()\n },\n getSnapshot: () => instance.snapshot,\n }\n }, [observable])\n\n return useSyncExternalStore<ObservedValueOf<ObservableType>>(store.subscribe, store.getSnapshot)\n}\n","import {observableCallback} from 'observable-callback'\nimport {useCallback, useEffect, useInsertionEffect, useRef, useState} from 'react'\nimport {type Observable} from 'rxjs'\n\n/** @public */\nexport function useObservableEvent<T, U>(\n fn: (arg: Observable<T>) => Observable<U>,\n): (arg: T) => void {\n const [[calls$, call]] = useState(() => observableCallback<T>())\n\n const callback = useEffectEvent(fn)\n\n useEffect(() => {\n const subscription = calls$.pipe(callback).subscribe()\n return () => subscription.unsubscribe()\n }, [callback, calls$])\n\n return call\n}\n\n/**\n * This is a ponyfill of the upcoming `useEffectEvent` hook that'll arrive in React 19\n */\nfunction useEffectEvent<\n const T extends (\n ...args: // eslint-disable-next-line @typescript-eslint/no-explicit-any\n any[]\n ) => void,\n>(fn: T): T {\n const ref = useRef<T | null>(null)\n useInsertionEffect(() => {\n ref.current = fn\n }, [fn])\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return useCallback((...args: any[]) => {\n const f = ref.current!\n return f(...args)\n }, []) as T\n}\n"],"names":[],"mappings":";;;AAIA,SAAS,SAAY,OAA2C;AAC9D,SAAO,OAAO,SAAU,aAAa,MAAA,IAAU;AACjD;AAOA,MAAM,4BAAY;AAGF,SAAA,cACd,YACA,cACiC;AAKjC,QAAM,kBAAkB,OAAO,SAAS,YAAY,CAAoC;AAKxF,YAAU,MAAM;AACE,oBAAA,UAAU,SAAS,YAAY;AAAA,EAAA,GAC9C,CAAC,YAAY,CAAC;AAEX,QAAA,QAAQ,QAAQ,MAAM;AAC1B,QAAI,CAAC,MAAM,IAAI,UAAU,GAAG;AAC1B,YAAM,QAA+D;AAAA,QACnE,UAAU,gBAAgB;AAAA,MAAA;AAE5B,YAAM,aAAa,WAAW;AAAA,QAC5B,YAAY,EAAC,UAAU,IAAM,YAAY,GAAE;AAAA,QAC3C,IAAI,CAAC,UAAW,MAAM,WAAW,KAAM;AAAA,MACzC,GAGA,MAAM,eAAe,MAAM,WAAW,aAEtC,MAAM,IAAI,YAAY,KAAqD;AAAA,IAC7E;AAEM,UAAA,WAAW,MAAM,IAAI,UAAU;AACjC,WAAA,SAAS,aAAa,WACxB,SAAS,eAAe,SAAS,WAAW,cAGvC;AAAA,MACL,WAAW,CAAC,kBAA8B;AACxC,cAAM,eAAe,SAAS,WAAW,UAAU,aAAa;AAChE,eAAA,SAAS,aAAa,YACf,GAAA,MAAM,aAAa;MAC5B;AAAA,MACA,aAAa,MAAM,SAAS;AAAA,IAAA;AAAA,EAC9B,GACC,CAAC,UAAU,CAAC;AAEf,SAAO,qBAAsD,MAAM,WAAW,MAAM,WAAW;AACjG;AC5DO,SAAS,mBACd,IACkB;AAClB,QAAM,CAAC,CAAC,QAAQ,IAAI,CAAC,IAAI,SAAS,MAAM,mBAAsB,CAAC,GAEzD,WAAW,eAAe,EAAE;AAElC,SAAA,UAAU,MAAM;AACd,UAAM,eAAe,OAAO,KAAK,QAAQ,EAAE,UAAU;AAC9C,WAAA,MAAM,aAAa;EACzB,GAAA,CAAC,UAAU,MAAM,CAAC,GAEd;AACT;AAKA,SAAS,eAKP,IAAU;AACJ,QAAA,MAAM,OAAiB,IAAI;AACjC,SAAA,mBAAmB,MAAM;AACvB,QAAI,UAAU;AAAA,KACb,CAAC,EAAE,CAAC,GAEA,YAAY,IAAI,SAAgB;AACrC,UAAM,IAAI,IAAI;AACP,WAAA,EAAE,GAAG,IAAI;AAAA,EAClB,GAAG,CAAE,CAAA;AACP;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-rx",
|
|
3
|
-
"version": "3.0.0-
|
|
3
|
+
"version": "3.0.0-6",
|
|
4
4
|
"description": "React + RxJS = <3",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"action",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"pipe",
|
|
16
16
|
"react",
|
|
17
17
|
"react18",
|
|
18
|
+
"react19",
|
|
18
19
|
"reactive",
|
|
19
20
|
"realtime",
|
|
20
21
|
"rx",
|
|
@@ -28,7 +29,6 @@
|
|
|
28
29
|
"sync",
|
|
29
30
|
"typesafe",
|
|
30
31
|
"typescript",
|
|
31
|
-
"use-sync-external-store",
|
|
32
32
|
"use"
|
|
33
33
|
],
|
|
34
34
|
"homepage": "https://react-rx.dev",
|
|
@@ -46,9 +46,18 @@
|
|
|
46
46
|
"Cody Olsen <stipsan@gmail.com> (https://github.com/stipsan)"
|
|
47
47
|
],
|
|
48
48
|
"sideEffects": false,
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
|
|
49
|
+
"type": "commonjs",
|
|
50
|
+
"exports": {
|
|
51
|
+
".": {
|
|
52
|
+
"source": "./src/index.ts",
|
|
53
|
+
"import": "./dist/index.mjs",
|
|
54
|
+
"default": "./dist/index.js"
|
|
55
|
+
},
|
|
56
|
+
"./package.json": "./package.json"
|
|
57
|
+
},
|
|
58
|
+
"main": "./dist/index.js",
|
|
59
|
+
"module": "./dist/index.mjs",
|
|
60
|
+
"types": "./dist/index.d.ts",
|
|
52
61
|
"files": [
|
|
53
62
|
"dist",
|
|
54
63
|
"src"
|
|
@@ -58,27 +67,24 @@
|
|
|
58
67
|
"."
|
|
59
68
|
],
|
|
60
69
|
"scripts": {
|
|
61
|
-
"build": "
|
|
62
|
-
"build:es2015": "tsc --module es2015 --target es2015 --outDir dist/es2015",
|
|
63
|
-
"build:esm": "tsc --module es2015 --target es5 --outDir dist/esm",
|
|
64
|
-
"build:cjs": "tsc --module commonjs --target es5 --outDir dist/cjs",
|
|
65
|
-
"clean": "rimraf dist",
|
|
70
|
+
"build": "pkg build --strict --clean --check",
|
|
66
71
|
"dev": "cd website && npm run dev",
|
|
67
|
-
"prepublishOnly": "npm run
|
|
68
|
-
"watch": "run
|
|
69
|
-
"test": "
|
|
72
|
+
"prepublishOnly": "npm run build",
|
|
73
|
+
"watch": "npm run build -- --watch",
|
|
74
|
+
"test": "vitest run",
|
|
70
75
|
"lint": "eslint --cache ."
|
|
71
76
|
},
|
|
77
|
+
"browserslist": "extends @sanity/browserslist-config",
|
|
72
78
|
"prettier": "@sanity/prettier-config",
|
|
73
79
|
"dependencies": {
|
|
74
80
|
"observable-callback": "^1.0.3"
|
|
75
81
|
},
|
|
76
82
|
"devDependencies": {
|
|
83
|
+
"@sanity/pkg-utils": "^6.9.3",
|
|
77
84
|
"@sanity/prettier-config": "^1.0.2",
|
|
78
|
-
"@sanity/semantic-release-preset": "^
|
|
85
|
+
"@sanity/semantic-release-preset": "^4.1.8",
|
|
79
86
|
"@testing-library/dom": "^10.1.0",
|
|
80
87
|
"@testing-library/react": "^16.0.0",
|
|
81
|
-
"@types/jest": "^29.5.3",
|
|
82
88
|
"@types/node": "^18.17.5",
|
|
83
89
|
"@types/react": "^18.3.3",
|
|
84
90
|
"@types/react-dom": "^18.3.0",
|
|
@@ -91,22 +97,18 @@
|
|
|
91
97
|
"eslint-plugin-react-compiler": "0.0.0-experimental-51a85ea-20240601",
|
|
92
98
|
"eslint-plugin-react-hooks": "^4.6.2",
|
|
93
99
|
"eslint-plugin-simple-import-sort": "^12.1.0",
|
|
94
|
-
"jest": "^29.6.2",
|
|
95
|
-
"jest-environment-jsdom": "^29.6.2",
|
|
96
|
-
"jsdom": "^20.0.3",
|
|
97
100
|
"npm-run-all": "^4.1.5",
|
|
98
101
|
"prettier": "^3.3.1",
|
|
99
102
|
"react": "^18.3.1",
|
|
100
103
|
"react-dom": "^18.3.1",
|
|
101
104
|
"react-test-renderer": "^18.3.1",
|
|
102
|
-
"rimraf": "^3.0.2",
|
|
103
105
|
"rxjs": "^7.8.1",
|
|
104
|
-
"
|
|
105
|
-
"typescript": "5.4.5"
|
|
106
|
+
"semantic-release": "^24.0.0",
|
|
107
|
+
"typescript": "5.4.5",
|
|
108
|
+
"vitest": "^1.6.0"
|
|
106
109
|
},
|
|
107
110
|
"peerDependencies": {
|
|
108
111
|
"react": "^18.3 || >=19.0.0-rc",
|
|
109
112
|
"rxjs": "^7"
|
|
110
|
-
}
|
|
111
|
-
"es2015": "dist/es2015/index.js"
|
|
113
|
+
}
|
|
112
114
|
}
|
|
@@ -2,6 +2,7 @@ import {act, render, renderHook} from '@testing-library/react'
|
|
|
2
2
|
import {createElement, Fragment} from 'react'
|
|
3
3
|
import {asyncScheduler, Observable, of, scheduled, Subject, timer} from 'rxjs'
|
|
4
4
|
import {mapTo} from 'rxjs/operators'
|
|
5
|
+
import {expect, test} from 'vitest'
|
|
5
6
|
|
|
6
7
|
import {useObservable} from '../useObservable'
|
|
7
8
|
|
package/src/useObservable.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {useEffect, useMemo, useRef, useSyncExternalStore} from 'react'
|
|
2
|
-
import type {Observable, Subscription} from 'rxjs'
|
|
2
|
+
import type {Observable, ObservedValueOf, Subscription} from 'rxjs'
|
|
3
3
|
import {shareReplay, tap} from 'rxjs/operators'
|
|
4
4
|
|
|
5
5
|
function getValue<T>(value: T): T extends () => infer U ? U : T {
|
|
@@ -13,26 +13,27 @@ interface CacheRecord<T> {
|
|
|
13
13
|
|
|
14
14
|
const cache = new WeakMap<Observable<any>, CacheRecord<any>>()
|
|
15
15
|
|
|
16
|
+
/** @public */
|
|
16
17
|
export function useObservable<ObservableType extends Observable<any>>(
|
|
17
18
|
observable: ObservableType,
|
|
18
|
-
initialValue?:
|
|
19
|
-
):
|
|
19
|
+
initialValue?: ObservedValueOf<ObservableType> | (() => ObservedValueOf<ObservableType>),
|
|
20
|
+
): ObservedValueOf<ObservableType> {
|
|
20
21
|
/**
|
|
21
22
|
* Store the initialValue in a ref, as we don't want a changed `initialValue` to trigger a re-subscription.
|
|
22
23
|
* But we also don't want the initialValue to be stale if the observable changes.
|
|
23
24
|
*/
|
|
24
|
-
const initialValueRef = useRef(getValue(initialValue) as
|
|
25
|
+
const initialValueRef = useRef(getValue(initialValue) as ObservedValueOf<ObservableType>)
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* Ensures that the initialValue is always up-to-date in case the observable changes.
|
|
28
29
|
*/
|
|
29
30
|
useEffect(() => {
|
|
30
|
-
initialValueRef.current = getValue(initialValue) as
|
|
31
|
+
initialValueRef.current = getValue(initialValue) as ObservedValueOf<ObservableType>
|
|
31
32
|
}, [initialValue])
|
|
32
33
|
|
|
33
34
|
const store = useMemo(() => {
|
|
34
35
|
if (!cache.has(observable)) {
|
|
35
|
-
const entry: Partial<CacheRecord<
|
|
36
|
+
const entry: Partial<CacheRecord<ObservedValueOf<ObservableType>>> = {
|
|
36
37
|
snapshot: initialValueRef.current,
|
|
37
38
|
}
|
|
38
39
|
entry.observable = observable.pipe(
|
|
@@ -43,7 +44,7 @@ export function useObservable<ObservableType extends Observable<any>>(
|
|
|
43
44
|
// Eagerly subscribe to sync set `entry.currentValue` to what the observable returns, and keep the observable alive until the component unmounts.
|
|
44
45
|
entry.subscription = entry.observable.subscribe()
|
|
45
46
|
|
|
46
|
-
cache.set(observable, entry as CacheRecord<
|
|
47
|
+
cache.set(observable, entry as CacheRecord<ObservedValueOf<ObservableType>>)
|
|
47
48
|
}
|
|
48
49
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
49
50
|
const instance = cache.get(observable)!
|
|
@@ -61,7 +62,5 @@ export function useObservable<ObservableType extends Observable<any>>(
|
|
|
61
62
|
}
|
|
62
63
|
}, [observable])
|
|
63
64
|
|
|
64
|
-
return useSyncExternalStore<
|
|
65
|
+
return useSyncExternalStore<ObservedValueOf<ObservableType>>(store.subscribe, store.getSnapshot)
|
|
65
66
|
}
|
|
66
|
-
|
|
67
|
-
type UnboxObservable<T> = T extends Observable<infer U> ? U : never
|
|
@@ -1,33 +1,8 @@
|
|
|
1
1
|
import {observableCallback} from 'observable-callback'
|
|
2
|
-
import {
|
|
3
|
-
import {Observable} from 'rxjs'
|
|
4
|
-
|
|
5
|
-
const EMPTY_DEPS: DependencyList = []
|
|
6
|
-
|
|
7
|
-
export function useObservableCallback<T, U>(
|
|
8
|
-
fn: (arg: Observable<T>) => Observable<U>,
|
|
9
|
-
dependencies: DependencyList = EMPTY_DEPS,
|
|
10
|
-
): (arg: T) => void {
|
|
11
|
-
const callbackRef = useRef<[Observable<T>, (val: T) => void]>()
|
|
12
|
-
|
|
13
|
-
if (!callbackRef.current) {
|
|
14
|
-
callbackRef.current = observableCallback<T>()
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const [calls$, call] = callbackRef.current
|
|
18
|
-
|
|
19
|
-
const callback = useCallback(fn, dependencies)
|
|
20
|
-
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
const subscription = calls$.pipe(callback).subscribe()
|
|
23
|
-
return () => {
|
|
24
|
-
subscription.unsubscribe()
|
|
25
|
-
}
|
|
26
|
-
}, [calls$, call, callback])
|
|
27
|
-
|
|
28
|
-
return call
|
|
29
|
-
}
|
|
2
|
+
import {useCallback, useEffect, useInsertionEffect, useRef, useState} from 'react'
|
|
3
|
+
import {type Observable} from 'rxjs'
|
|
30
4
|
|
|
5
|
+
/** @public */
|
|
31
6
|
export function useObservableEvent<T, U>(
|
|
32
7
|
fn: (arg: Observable<T>) => Observable<U>,
|
|
33
8
|
): (arg: T) => void {
|
|
@@ -46,7 +21,7 @@ export function useObservableEvent<T, U>(
|
|
|
46
21
|
/**
|
|
47
22
|
* This is a ponyfill of the upcoming `useEffectEvent` hook that'll arrive in React 19
|
|
48
23
|
*/
|
|
49
|
-
|
|
24
|
+
function useEffectEvent<
|
|
50
25
|
const T extends (
|
|
51
26
|
...args: // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
52
27
|
any[]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
var react_1 = require("@testing-library/react");
|
|
40
|
-
var react_2 = require("react");
|
|
41
|
-
var rxjs_1 = require("rxjs");
|
|
42
|
-
var useObservable_1 = require("../useObservable");
|
|
43
|
-
var wait = function (ms) { return new Promise(function (resolve) { return setTimeout(resolve, ms); }); };
|
|
44
|
-
// NOTE: Jest runs NODE_ENV=test by default, which enables development flags for React
|
|
45
|
-
test('Strict mode should trigger double mount effects and re-renders', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
46
|
-
function ObservableComponent() {
|
|
47
|
-
(0, react_2.useEffect)(function () {
|
|
48
|
-
mountCount++;
|
|
49
|
-
}, []);
|
|
50
|
-
var observedValue = (0, useObservable_1.useObservable)(observable);
|
|
51
|
-
returnedValues.push(observedValue);
|
|
52
|
-
return (0, react_2.createElement)(react_2.Fragment, null, observedValue);
|
|
53
|
-
}
|
|
54
|
-
var subject, observable, returnedValues, mountCount;
|
|
55
|
-
return __generator(this, function (_a) {
|
|
56
|
-
switch (_a.label) {
|
|
57
|
-
case 0:
|
|
58
|
-
subject = new rxjs_1.BehaviorSubject(0);
|
|
59
|
-
observable = subject.asObservable();
|
|
60
|
-
returnedValues = [];
|
|
61
|
-
mountCount = 0;
|
|
62
|
-
(0, react_1.render)((0, react_2.createElement)(react_2.StrictMode, null, (0, react_2.createElement)(ObservableComponent)));
|
|
63
|
-
expect(mountCount).toEqual(2);
|
|
64
|
-
expect(returnedValues).toEqual([0, 0]);
|
|
65
|
-
return [4 /*yield*/, wait(10)];
|
|
66
|
-
case 1:
|
|
67
|
-
_a.sent();
|
|
68
|
-
(0, react_1.act)(function () { return subject.next(1); });
|
|
69
|
-
expect(returnedValues).toEqual([0, 0, 1, 1]);
|
|
70
|
-
(0, react_1.act)(function () { return subject.next(2); });
|
|
71
|
-
expect(returnedValues).toEqual([0, 0, 1, 1, 2, 2]);
|
|
72
|
-
expect(mountCount).toEqual(2);
|
|
73
|
-
return [2 /*return*/];
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
}); });
|
|
77
|
-
test('Strict mode should unsubscribe the source observable on unmount', function () {
|
|
78
|
-
var subscribed = [];
|
|
79
|
-
var unsubscribed = [];
|
|
80
|
-
var nextId = 0;
|
|
81
|
-
var observable = new rxjs_1.Observable(function () {
|
|
82
|
-
var id = nextId++;
|
|
83
|
-
subscribed.push(id);
|
|
84
|
-
return function () {
|
|
85
|
-
unsubscribed.push(id);
|
|
86
|
-
};
|
|
87
|
-
});
|
|
88
|
-
function ObservableComponent() {
|
|
89
|
-
(0, useObservable_1.useObservable)(observable);
|
|
90
|
-
return (0, react_2.createElement)(react_2.Fragment, null);
|
|
91
|
-
}
|
|
92
|
-
var rerender = (0, react_1.render)((0, react_2.createElement)(react_2.StrictMode, null, (0, react_2.createElement)(ObservableComponent))).rerender;
|
|
93
|
-
expect(subscribed).toEqual([0, 1]);
|
|
94
|
-
rerender((0, react_2.createElement)(react_2.StrictMode, null, (0, react_2.createElement)('div')));
|
|
95
|
-
expect(unsubscribed).toEqual([0, 1]);
|
|
96
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
var react_1 = require("@testing-library/react");
|
|
4
|
-
var react_2 = require("react");
|
|
5
|
-
var rxjs_1 = require("rxjs");
|
|
6
|
-
var operators_1 = require("rxjs/operators");
|
|
7
|
-
var useObservable_1 = require("../useObservable");
|
|
8
|
-
test('should subscribe immediately on component mount and unsubscribe on component unmount', function () {
|
|
9
|
-
var subscribed = false;
|
|
10
|
-
var observable = new rxjs_1.Observable(function () {
|
|
11
|
-
subscribed = true;
|
|
12
|
-
return function () {
|
|
13
|
-
subscribed = false;
|
|
14
|
-
};
|
|
15
|
-
});
|
|
16
|
-
expect(subscribed).toBe(false);
|
|
17
|
-
var unmount = (0, react_1.renderHook)(function () { return (0, useObservable_1.useObservable)(observable); }).unmount;
|
|
18
|
-
expect(subscribed).toBe(true);
|
|
19
|
-
unmount();
|
|
20
|
-
expect(subscribed).toBe(false);
|
|
21
|
-
});
|
|
22
|
-
test('should only subscribe once when given same observable on re-renders', function () {
|
|
23
|
-
var subscriptionCount = 0;
|
|
24
|
-
var observable = new rxjs_1.Observable(function () {
|
|
25
|
-
subscriptionCount++;
|
|
26
|
-
});
|
|
27
|
-
expect(subscriptionCount).toBe(0);
|
|
28
|
-
var _a = (0, react_1.renderHook)(function () { return (0, useObservable_1.useObservable)(observable); }), unmount = _a.unmount, rerender = _a.rerender;
|
|
29
|
-
expect(subscriptionCount).toBe(1);
|
|
30
|
-
rerender();
|
|
31
|
-
expect(subscriptionCount).toBe(1);
|
|
32
|
-
unmount();
|
|
33
|
-
(0, react_1.renderHook)(function () { return (0, useObservable_1.useObservable)(observable); });
|
|
34
|
-
expect(subscriptionCount).toBe(2);
|
|
35
|
-
});
|
|
36
|
-
test('should not return undefined during render if initial value is given', function () {
|
|
37
|
-
var observable = (0, rxjs_1.timer)(100).pipe((0, operators_1.mapTo)('emitted value'));
|
|
38
|
-
var returnedValues = [];
|
|
39
|
-
function ObservableComponent() {
|
|
40
|
-
var observedValue = (0, useObservable_1.useObservable)(observable, 'initial value');
|
|
41
|
-
returnedValues.push(observedValue);
|
|
42
|
-
return (0, react_2.createElement)(react_2.Fragment, null, observedValue);
|
|
43
|
-
}
|
|
44
|
-
(0, react_1.render)((0, react_2.createElement)(ObservableComponent));
|
|
45
|
-
expect(returnedValues).toEqual(expect.arrayContaining(['initial value']));
|
|
46
|
-
});
|
|
47
|
-
test('should not return undefined during render if observable is sync', function () {
|
|
48
|
-
var observable = (0, rxjs_1.of)('initial value');
|
|
49
|
-
var returnedValues = [];
|
|
50
|
-
function ObservableComponent() {
|
|
51
|
-
var observedValue = (0, useObservable_1.useObservable)(observable);
|
|
52
|
-
returnedValues.push(observedValue);
|
|
53
|
-
return (0, react_2.createElement)(react_2.Fragment, null, observedValue);
|
|
54
|
-
}
|
|
55
|
-
(0, react_1.render)((0, react_2.createElement)(ObservableComponent));
|
|
56
|
-
expect(returnedValues).toEqual(expect.arrayContaining(['initial value']));
|
|
57
|
-
});
|
|
58
|
-
test('should return undefined during first render if observable is async', function () {
|
|
59
|
-
var observable = (0, rxjs_1.scheduled)('async value', rxjs_1.asyncScheduler);
|
|
60
|
-
var returnedValues = [];
|
|
61
|
-
function ObservableComponent() {
|
|
62
|
-
var observedValue = (0, useObservable_1.useObservable)(observable);
|
|
63
|
-
returnedValues.push(observedValue);
|
|
64
|
-
return (0, react_2.createElement)(react_2.Fragment, null, observedValue);
|
|
65
|
-
}
|
|
66
|
-
(0, react_1.render)((0, react_2.createElement)(ObservableComponent));
|
|
67
|
-
expect(returnedValues).toEqual(expect.arrayContaining([undefined]));
|
|
68
|
-
});
|
|
69
|
-
test('should have sync values from an observable as initial value', function () {
|
|
70
|
-
var observable = (0, rxjs_1.of)('something sync');
|
|
71
|
-
var result = (0, react_1.renderHook)(function () { return (0, useObservable_1.useObservable)(observable); }).result;
|
|
72
|
-
expect(result.current).toBe('something sync');
|
|
73
|
-
});
|
|
74
|
-
test('should have undefined as initial value from delayed observables', function () {
|
|
75
|
-
var _a = (0, react_1.renderHook)(function () {
|
|
76
|
-
return (0, useObservable_1.useObservable)((0, rxjs_1.scheduled)('something async', rxjs_1.asyncScheduler));
|
|
77
|
-
}), result = _a.result, unmount = _a.unmount;
|
|
78
|
-
expect(result.current).toBeUndefined();
|
|
79
|
-
unmount();
|
|
80
|
-
});
|
|
81
|
-
test('should have passed initialValue as initial value from delayed observables', function () {
|
|
82
|
-
var _a = (0, react_1.renderHook)(function () {
|
|
83
|
-
return (0, useObservable_1.useObservable)((0, rxjs_1.scheduled)('something async', rxjs_1.asyncScheduler), 'initial');
|
|
84
|
-
}), result = _a.result, unmount = _a.unmount;
|
|
85
|
-
expect(result.current).toBe('initial');
|
|
86
|
-
unmount();
|
|
87
|
-
});
|
|
88
|
-
test('should update with values from observables', function () {
|
|
89
|
-
var values$ = new rxjs_1.Subject();
|
|
90
|
-
var _a = (0, react_1.renderHook)(function () { return (0, useObservable_1.useObservable)(values$); }), result = _a.result, unmount = _a.unmount;
|
|
91
|
-
expect(result.current).toBe(undefined);
|
|
92
|
-
(0, react_1.act)(function () { return values$.next('something'); });
|
|
93
|
-
expect(result.current).toBe('something');
|
|
94
|
-
(0, react_1.act)(function () { return values$.next('otherthing'); });
|
|
95
|
-
expect(result.current).toBe('otherthing');
|
|
96
|
-
unmount();
|
|
97
|
-
});
|
|
98
|
-
test('should re-subscribe when receiving a new observable', function () {
|
|
99
|
-
var first$ = new rxjs_1.Subject();
|
|
100
|
-
var second$ = new rxjs_1.Subject();
|
|
101
|
-
var current$ = first$;
|
|
102
|
-
var _a = (0, react_1.renderHook)(function () { return (0, useObservable_1.useObservable)(current$, '!!initial!!'); }), result = _a.result, rerender = _a.rerender, unmount = _a.unmount;
|
|
103
|
-
(0, react_1.act)(function () { return first$.next('first 1'); });
|
|
104
|
-
expect(result.current).toBe('first 1');
|
|
105
|
-
current$ = second$;
|
|
106
|
-
rerender();
|
|
107
|
-
// since observable #2 hasn't emitted a value yet, we should use the initial value
|
|
108
|
-
expect(result.current).toBe('!!initial!!');
|
|
109
|
-
// Now we should be subscribed to second$ and it's emission should be returned
|
|
110
|
-
(0, react_1.act)(function () { return second$.next('second 1'); });
|
|
111
|
-
expect(result.current).toBe('second 1');
|
|
112
|
-
// we should no longer be subscribed to the first and ignore any emissions
|
|
113
|
-
(0, react_1.act)(function () { return first$.next('first 2'); });
|
|
114
|
-
expect(result.current).toBe('second 1');
|
|
115
|
-
unmount();
|
|
116
|
-
});
|
package/dist/cjs/index.d.ts
DELETED
package/dist/cjs/index.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./useObservable"), exports);
|
|
18
|
-
__exportStar(require("./useObservableEvent"), exports);
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { Observable } from 'rxjs';
|
|
2
|
-
export declare function useObservable<ObservableType extends Observable<any>>(observable: ObservableType, initialValue?: UnboxObservable<ObservableType> | (() => UnboxObservable<ObservableType>)): UnboxObservable<ObservableType>;
|
|
3
|
-
type UnboxObservable<T> = T extends Observable<infer U> ? U : never;
|
|
4
|
-
export {};
|