react-rx 2.1.3 → 3.0.0-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/dist/cjs/__tests__/strictmode.test.js +19 -34
- package/dist/cjs/__tests__/useObservable.test.js +2 -2
- package/dist/cjs/index.d.ts +2 -7
- package/dist/cjs/index.js +16 -26
- package/dist/cjs/useObservable.d.ts +0 -3
- package/dist/cjs/useObservable.js +15 -9
- package/dist/cjs/{useObservableCallback.js → useObservableEvent.js} +1 -2
- package/dist/es2015/__tests__/strictmode.test.js +11 -22
- package/dist/es2015/__tests__/useObservable.test.js +2 -2
- package/dist/es2015/index.d.ts +2 -7
- package/dist/es2015/index.js +2 -9
- package/dist/es2015/useObservable.d.ts +0 -3
- package/dist/es2015/useObservable.js +14 -7
- package/dist/es2015/{useObservableCallback.js → useObservableEvent.js} +1 -2
- package/dist/esm/__tests__/strictmode.test.js +12 -27
- package/dist/esm/__tests__/useObservable.test.js +2 -2
- package/dist/esm/index.d.ts +2 -7
- package/dist/esm/index.js +2 -9
- package/dist/esm/useObservable.d.ts +0 -3
- package/dist/esm/useObservable.js +14 -7
- package/dist/esm/{useObservableCallback.js → useObservableEvent.js} +1 -2
- package/package.json +30 -29
- package/src/__tests__/strictmode.test.ts +13 -30
- package/src/__tests__/useObservable.test.tsx +3 -2
- package/src/index.ts +2 -15
- package/src/useObservable.ts +16 -24
- package/src/{useObservableCallback.ts → useObservableEvent.ts} +1 -2
- package/dist/cjs/WithObservable.d.ts +0 -12
- package/dist/cjs/WithObservable.js +0 -16
- package/dist/cjs/__tests__/useAsObservable.test.d.ts +0 -1
- package/dist/cjs/__tests__/useAsObservable.test.js +0 -77
- package/dist/cjs/displayName.d.ts +0 -1
- package/dist/cjs/displayName.js +0 -14
- package/dist/cjs/reactiveComponent.d.ts +0 -8
- package/dist/cjs/reactiveComponent.js +0 -35
- package/dist/cjs/useAsObservable.d.ts +0 -10
- package/dist/cjs/useAsObservable.js +0 -47
- package/dist/cjs/useWithObservable.d.ts +0 -9
- package/dist/cjs/useWithObservable.js +0 -11
- package/dist/cjs/utils.d.ts +0 -7
- package/dist/cjs/utils.js +0 -38
- package/dist/cjs/withPropsStream.d.ts +0 -8
- package/dist/cjs/withPropsStream.js +0 -55
- package/dist/es2015/WithObservable.d.ts +0 -12
- package/dist/es2015/WithObservable.js +0 -9
- package/dist/es2015/__tests__/useAsObservable.test.d.ts +0 -1
- package/dist/es2015/__tests__/useAsObservable.test.js +0 -72
- package/dist/es2015/displayName.d.ts +0 -1
- package/dist/es2015/displayName.js +0 -8
- package/dist/es2015/reactiveComponent.d.ts +0 -8
- package/dist/es2015/reactiveComponent.js +0 -30
- package/dist/es2015/useAsObservable.d.ts +0 -10
- package/dist/es2015/useAsObservable.js +0 -43
- package/dist/es2015/useWithObservable.d.ts +0 -9
- package/dist/es2015/useWithObservable.js +0 -7
- package/dist/es2015/utils.d.ts +0 -7
- package/dist/es2015/utils.js +0 -31
- package/dist/es2015/withPropsStream.d.ts +0 -8
- package/dist/es2015/withPropsStream.js +0 -17
- package/dist/esm/WithObservable.d.ts +0 -12
- package/dist/esm/WithObservable.js +0 -13
- package/dist/esm/__tests__/useAsObservable.test.d.ts +0 -1
- package/dist/esm/__tests__/useAsObservable.test.js +0 -72
- package/dist/esm/displayName.d.ts +0 -1
- package/dist/esm/displayName.js +0 -10
- package/dist/esm/reactiveComponent.d.ts +0 -8
- package/dist/esm/reactiveComponent.js +0 -30
- package/dist/esm/useAsObservable.d.ts +0 -10
- package/dist/esm/useAsObservable.js +0 -43
- package/dist/esm/useWithObservable.d.ts +0 -9
- package/dist/esm/useWithObservable.js +0 -7
- package/dist/esm/utils.d.ts +0 -7
- package/dist/esm/utils.js +0 -31
- package/dist/esm/withPropsStream.d.ts +0 -8
- package/dist/esm/withPropsStream.js +0 -28
- package/src/WithObservable.tsx +0 -29
- package/src/__tests__/useAsObservable.test.tsx +0 -94
- package/src/displayName.ts +0 -11
- package/src/reactiveComponent.ts +0 -63
- package/src/useAsObservable.ts +0 -66
- package/src/useWithObservable.ts +0 -24
- package/src/utils.ts +0 -48
- package/src/withPropsStream.tsx +0 -27
- /package/dist/cjs/{useObservableCallback.d.ts → useObservableEvent.d.ts} +0 -0
- /package/dist/es2015/{useObservableCallback.d.ts → useObservableEvent.d.ts} +0 -0
- /package/dist/esm/{useObservableCallback.d.ts → useObservableEvent.d.ts} +0 -0
|
@@ -36,23 +36,22 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
var react_1 = require("@testing-library/react");
|
|
40
|
+
var react_2 = require("react");
|
|
39
41
|
var rxjs_1 = require("rxjs");
|
|
40
42
|
var useObservable_1 = require("../useObservable");
|
|
41
|
-
var react_1 = require("react");
|
|
42
|
-
var react_2 = require("@testing-library/react");
|
|
43
|
-
var useAsObservable_1 = require("../useAsObservable");
|
|
44
43
|
var wait = function (ms) { return new Promise(function (resolve) { return setTimeout(resolve, ms); }); };
|
|
45
44
|
// NOTE: Jest runs NODE_ENV=test by default, which enables development flags for React
|
|
46
45
|
test('Strict mode should trigger double mount effects and re-renders', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
47
46
|
function ObservableComponent() {
|
|
48
|
-
(0,
|
|
47
|
+
(0, react_2.useEffect)(function () {
|
|
49
48
|
mountCount++;
|
|
50
49
|
}, []);
|
|
51
50
|
var observedValue = (0, useObservable_1.useObservable)(observable);
|
|
52
51
|
returnedValues.push(observedValue);
|
|
53
|
-
return (0,
|
|
52
|
+
return (0, react_2.createElement)(react_2.Fragment, null, observedValue);
|
|
54
53
|
}
|
|
55
|
-
var subject, observable, returnedValues, mountCount
|
|
54
|
+
var subject, observable, returnedValues, mountCount;
|
|
56
55
|
return __generator(this, function (_a) {
|
|
57
56
|
switch (_a.label) {
|
|
58
57
|
case 0:
|
|
@@ -60,15 +59,15 @@ test('Strict mode should trigger double mount effects and re-renders', function
|
|
|
60
59
|
observable = subject.asObservable();
|
|
61
60
|
returnedValues = [];
|
|
62
61
|
mountCount = 0;
|
|
63
|
-
|
|
62
|
+
(0, react_1.render)((0, react_2.createElement)(react_2.StrictMode, null, (0, react_2.createElement)(ObservableComponent)));
|
|
64
63
|
expect(mountCount).toEqual(2);
|
|
65
64
|
expect(returnedValues).toEqual([0, 0]);
|
|
66
65
|
return [4 /*yield*/, wait(10)];
|
|
67
66
|
case 1:
|
|
68
67
|
_a.sent();
|
|
69
|
-
(0,
|
|
68
|
+
(0, react_1.act)(function () { return subject.next(1); });
|
|
70
69
|
expect(returnedValues).toEqual([0, 0, 1, 1]);
|
|
71
|
-
(0,
|
|
70
|
+
(0, react_1.act)(function () { return subject.next(2); });
|
|
72
71
|
expect(returnedValues).toEqual([0, 0, 1, 1, 2, 2]);
|
|
73
72
|
expect(mountCount).toEqual(2);
|
|
74
73
|
return [2 /*return*/];
|
|
@@ -76,36 +75,22 @@ test('Strict mode should trigger double mount effects and re-renders', function
|
|
|
76
75
|
});
|
|
77
76
|
}); });
|
|
78
77
|
test('Strict mode should unsubscribe the source observable on unmount', function () {
|
|
79
|
-
var subscribed =
|
|
78
|
+
var subscribed = [];
|
|
79
|
+
var unsubscribed = [];
|
|
80
|
+
var nextId = 0;
|
|
80
81
|
var observable = new rxjs_1.Observable(function () {
|
|
81
|
-
|
|
82
|
+
var id = nextId++;
|
|
83
|
+
subscribed.push(id);
|
|
82
84
|
return function () {
|
|
83
|
-
|
|
85
|
+
unsubscribed.push(id);
|
|
84
86
|
};
|
|
85
87
|
});
|
|
86
88
|
function ObservableComponent() {
|
|
87
89
|
(0, useObservable_1.useObservable)(observable);
|
|
88
|
-
return (0,
|
|
90
|
+
return (0, react_2.createElement)(react_2.Fragment, null);
|
|
89
91
|
}
|
|
90
|
-
var rerender = (0,
|
|
91
|
-
expect(subscribed).
|
|
92
|
-
rerender((0,
|
|
93
|
-
expect(
|
|
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]);
|
|
94
96
|
});
|
|
95
|
-
test('useAsObservable should work in strict mode', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
96
|
-
function ObservableComponent(props) {
|
|
97
|
-
var count$ = (0, useAsObservable_1.useAsObservable)(props.count);
|
|
98
|
-
var count = (0, useObservable_1.useObservable)(count$);
|
|
99
|
-
returnedValues.push(count);
|
|
100
|
-
return (0, react_1.createElement)(react_1.Fragment, null, 'ok');
|
|
101
|
-
}
|
|
102
|
-
var returnedValues, rerender;
|
|
103
|
-
return __generator(this, function (_a) {
|
|
104
|
-
returnedValues = [];
|
|
105
|
-
rerender = (0, react_2.render)((0, react_1.createElement)(react_1.StrictMode, null, (0, react_1.createElement)(ObservableComponent, { count: 0 }))).rerender;
|
|
106
|
-
expect(returnedValues).toEqual([0, 0]);
|
|
107
|
-
rerender((0, react_1.createElement)(react_1.StrictMode, null, (0, react_1.createElement)(ObservableComponent, { count: 1 })));
|
|
108
|
-
expect(returnedValues).toEqual([0, 0, 0, 0, 1, 1]);
|
|
109
|
-
return [2 /*return*/];
|
|
110
|
-
});
|
|
111
|
-
}); });
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
var react_1 = require("@testing-library/react");
|
|
4
|
-
var
|
|
4
|
+
var react_2 = require("react");
|
|
5
5
|
var rxjs_1 = require("rxjs");
|
|
6
6
|
var operators_1 = require("rxjs/operators");
|
|
7
|
-
var
|
|
7
|
+
var useObservable_1 = require("../useObservable");
|
|
8
8
|
test('should subscribe immediately on component mount and unsubscribe on component unmount', function () {
|
|
9
9
|
var subscribed = false;
|
|
10
10
|
var observable = new rxjs_1.Observable(function () {
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export { observeState as state, observeCallback as handler, observeContext as context, observeElement as elementRef, } from './utils';
|
|
4
|
-
export { observableCallback } from 'observable-callback';
|
|
5
|
-
export { useObservable, useMemoObservable } from './useObservable';
|
|
6
|
-
export { useAsObservable } from './useAsObservable';
|
|
7
|
-
export { useObservableCallback } from './useObservableCallback';
|
|
1
|
+
export * from './useObservable';
|
|
2
|
+
export * from './useObservableEvent';
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,28 +1,18 @@
|
|
|
1
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
|
+
};
|
|
2
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
var reactiveComponent_1 = require("./reactiveComponent");
|
|
6
|
-
Object.defineProperty(exports, "reactiveComponent", { enumerable: true, get: function () { return reactiveComponent_1.reactiveComponent; } });
|
|
7
|
-
Object.defineProperty(exports, "rxComponent", { enumerable: true, get: function () { return reactiveComponent_1.reactiveComponent; } });
|
|
8
|
-
Object.defineProperty(exports, "forwardRef", { enumerable: true, get: function () { return reactiveComponent_1.forwardRef; } });
|
|
9
|
-
var utils_1 = require("./utils");
|
|
10
|
-
Object.defineProperty(exports, "observeState", { enumerable: true, get: function () { return utils_1.observeState; } });
|
|
11
|
-
Object.defineProperty(exports, "observeCallback", { enumerable: true, get: function () { return utils_1.observeCallback; } });
|
|
12
|
-
Object.defineProperty(exports, "observeContext", { enumerable: true, get: function () { return utils_1.observeContext; } });
|
|
13
|
-
Object.defineProperty(exports, "observeElement", { enumerable: true, get: function () { return utils_1.observeElement; } });
|
|
14
|
-
var utils_2 = require("./utils");
|
|
15
|
-
Object.defineProperty(exports, "state", { enumerable: true, get: function () { return utils_2.observeState; } });
|
|
16
|
-
Object.defineProperty(exports, "handler", { enumerable: true, get: function () { return utils_2.observeCallback; } });
|
|
17
|
-
Object.defineProperty(exports, "context", { enumerable: true, get: function () { return utils_2.observeContext; } });
|
|
18
|
-
Object.defineProperty(exports, "elementRef", { enumerable: true, get: function () { return utils_2.observeElement; } });
|
|
19
|
-
var observable_callback_1 = require("observable-callback");
|
|
20
|
-
Object.defineProperty(exports, "observableCallback", { enumerable: true, get: function () { return observable_callback_1.observableCallback; } });
|
|
21
|
-
// hooks
|
|
22
|
-
var useObservable_1 = require("./useObservable");
|
|
23
|
-
Object.defineProperty(exports, "useObservable", { enumerable: true, get: function () { return useObservable_1.useObservable; } });
|
|
24
|
-
Object.defineProperty(exports, "useMemoObservable", { enumerable: true, get: function () { return useObservable_1.useMemoObservable; } });
|
|
25
|
-
var useAsObservable_1 = require("./useAsObservable");
|
|
26
|
-
Object.defineProperty(exports, "useAsObservable", { enumerable: true, get: function () { return useAsObservable_1.useAsObservable; } });
|
|
27
|
-
var useObservableCallback_1 = require("./useObservableCallback");
|
|
28
|
-
Object.defineProperty(exports, "useObservableCallback", { enumerable: true, get: function () { return useObservableCallback_1.useObservableCallback; } });
|
|
17
|
+
__exportStar(require("./useObservable"), exports);
|
|
18
|
+
__exportStar(require("./useObservableEvent"), exports);
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
|
-
import { DependencyList } from 'react';
|
|
3
2
|
export declare function useObservable<T>(observable: Observable<T>): T | undefined;
|
|
4
3
|
export declare function useObservable<T>(observable: Observable<T>, initialValue: T): T;
|
|
5
4
|
export declare function useObservable<T>(observable: Observable<T>, initialValue: () => T): T;
|
|
6
|
-
export declare function useMemoObservable<T>(observableOrFactory: Observable<T> | (() => Observable<T>), deps: DependencyList): T | undefined;
|
|
7
|
-
export declare function useMemoObservable<T>(observableOrFactory: Observable<T> | (() => Observable<T>), deps: DependencyList, initialValue: T | (() => T)): T;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.useObservable = void 0;
|
|
4
4
|
var react_1 = require("react");
|
|
5
|
-
var shim_1 = require("use-sync-external-store/shim");
|
|
6
5
|
var operators_1 = require("rxjs/operators");
|
|
7
6
|
function getValue(value) {
|
|
8
7
|
return typeof value === 'function' ? value() : value;
|
|
@@ -19,8 +18,19 @@ function getOrCreateStore(inputObservable, initialValue) {
|
|
|
19
18
|
return cache.get(inputObservable);
|
|
20
19
|
}
|
|
21
20
|
function useObservable(observable, initialValue) {
|
|
21
|
+
/**
|
|
22
|
+
* Store the initialValue in a ref, as we don't want a changed `initialValue` to trigger a re-subscription.
|
|
23
|
+
* But we also don't want the initialValue to be stale if the observable changes.
|
|
24
|
+
*/
|
|
25
|
+
var initialValueRef = (0, react_1.useRef)(getValue(initialValue));
|
|
26
|
+
/**
|
|
27
|
+
* Ensures that the initialValue is always up-to-date in case the observable changes.
|
|
28
|
+
*/
|
|
29
|
+
(0, react_1.useEffect)(function () {
|
|
30
|
+
initialValueRef.current = getValue(initialValue);
|
|
31
|
+
}, [initialValue]);
|
|
22
32
|
var _a = (0, react_1.useMemo)(function () {
|
|
23
|
-
var store = getOrCreateStore(observable,
|
|
33
|
+
var store = getOrCreateStore(observable, initialValueRef.current);
|
|
24
34
|
if (store.subscription.closed) {
|
|
25
35
|
store.subscription = store.observable.subscribe();
|
|
26
36
|
}
|
|
@@ -40,7 +50,7 @@ function useObservable(observable, initialValue) {
|
|
|
40
50
|
}, [observable]), getSnapshot = _a[0], subscribe = _a[1];
|
|
41
51
|
var shouldRestoreSubscriptionRef = (0, react_1.useRef)(false);
|
|
42
52
|
(0, react_1.useEffect)(function () {
|
|
43
|
-
var store = getOrCreateStore(observable,
|
|
53
|
+
var store = getOrCreateStore(observable, initialValueRef.current);
|
|
44
54
|
if (shouldRestoreSubscriptionRef.current) {
|
|
45
55
|
if (store.subscription.closed) {
|
|
46
56
|
store.subscription = store.observable.subscribe();
|
|
@@ -54,10 +64,6 @@ function useObservable(observable, initialValue) {
|
|
|
54
64
|
store.subscription.unsubscribe();
|
|
55
65
|
};
|
|
56
66
|
}, [observable]);
|
|
57
|
-
return (0,
|
|
67
|
+
return (0, react_1.useSyncExternalStore)(subscribe, getSnapshot);
|
|
58
68
|
}
|
|
59
69
|
exports.useObservable = useObservable;
|
|
60
|
-
function useMemoObservable(observableOrFactory, deps, initialValue) {
|
|
61
|
-
return useObservable((0, react_1.useMemo)(function () { return getValue(observableOrFactory); }, deps), initialValue);
|
|
62
|
-
}
|
|
63
|
-
exports.useMemoObservable = useMemoObservable;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useObservableCallback = void 0;
|
|
4
|
-
var react_1 = require("react");
|
|
5
4
|
var observable_callback_1 = require("observable-callback");
|
|
5
|
+
var react_1 = require("react");
|
|
6
6
|
var EMPTY_DEPS = [];
|
|
7
7
|
function useObservableCallback(fn, dependencies) {
|
|
8
8
|
if (dependencies === void 0) { dependencies = EMPTY_DEPS; }
|
|
@@ -11,7 +11,6 @@ function useObservableCallback(fn, dependencies) {
|
|
|
11
11
|
callbackRef.current = (0, observable_callback_1.observableCallback)();
|
|
12
12
|
}
|
|
13
13
|
var _a = callbackRef.current, calls$ = _a[0], call = _a[1];
|
|
14
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
15
14
|
var callback = (0, react_1.useCallback)(fn, dependencies);
|
|
16
15
|
(0, react_1.useEffect)(function () {
|
|
17
16
|
var subscription = calls$.pipe(callback).subscribe();
|
|
@@ -7,11 +7,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
+
import { act, render } from '@testing-library/react';
|
|
11
|
+
import { createElement, Fragment, StrictMode, useEffect } from 'react';
|
|
10
12
|
import { BehaviorSubject, Observable } from 'rxjs';
|
|
11
13
|
import { useObservable } from '../useObservable';
|
|
12
|
-
import { createElement, Fragment, StrictMode, useEffect } from 'react';
|
|
13
|
-
import { act, render } from '@testing-library/react';
|
|
14
|
-
import { useAsObservable } from '../useAsObservable';
|
|
15
14
|
const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
16
15
|
// NOTE: Jest runs NODE_ENV=test by default, which enables development flags for React
|
|
17
16
|
test('Strict mode should trigger double mount effects and re-renders', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -27,7 +26,7 @@ test('Strict mode should trigger double mount effects and re-renders', () => __a
|
|
|
27
26
|
returnedValues.push(observedValue);
|
|
28
27
|
return createElement(Fragment, null, observedValue);
|
|
29
28
|
}
|
|
30
|
-
|
|
29
|
+
render(createElement(StrictMode, null, createElement(ObservableComponent)));
|
|
31
30
|
expect(mountCount).toEqual(2);
|
|
32
31
|
expect(returnedValues).toEqual([0, 0]);
|
|
33
32
|
yield wait(10);
|
|
@@ -38,11 +37,14 @@ test('Strict mode should trigger double mount effects and re-renders', () => __a
|
|
|
38
37
|
expect(mountCount).toEqual(2);
|
|
39
38
|
}));
|
|
40
39
|
test('Strict mode should unsubscribe the source observable on unmount', () => {
|
|
41
|
-
|
|
40
|
+
const subscribed = [];
|
|
41
|
+
const unsubscribed = [];
|
|
42
|
+
let nextId = 0;
|
|
42
43
|
const observable = new Observable(() => {
|
|
43
|
-
|
|
44
|
+
const id = nextId++;
|
|
45
|
+
subscribed.push(id);
|
|
44
46
|
return () => {
|
|
45
|
-
|
|
47
|
+
unsubscribed.push(id);
|
|
46
48
|
};
|
|
47
49
|
});
|
|
48
50
|
function ObservableComponent() {
|
|
@@ -50,20 +52,7 @@ test('Strict mode should unsubscribe the source observable on unmount', () => {
|
|
|
50
52
|
return createElement(Fragment, null);
|
|
51
53
|
}
|
|
52
54
|
const { rerender } = render(createElement(StrictMode, null, createElement(ObservableComponent)));
|
|
53
|
-
expect(subscribed).
|
|
55
|
+
expect(subscribed).toEqual([0, 1]);
|
|
54
56
|
rerender(createElement(StrictMode, null, createElement('div')));
|
|
55
|
-
expect(
|
|
57
|
+
expect(unsubscribed).toEqual([0, 1]);
|
|
56
58
|
});
|
|
57
|
-
test('useAsObservable should work in strict mode', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
58
|
-
const returnedValues = [];
|
|
59
|
-
function ObservableComponent(props) {
|
|
60
|
-
const count$ = useAsObservable(props.count);
|
|
61
|
-
const count = useObservable(count$);
|
|
62
|
-
returnedValues.push(count);
|
|
63
|
-
return createElement(Fragment, null, 'ok');
|
|
64
|
-
}
|
|
65
|
-
const { rerender } = render(createElement(StrictMode, null, createElement(ObservableComponent, { count: 0 })));
|
|
66
|
-
expect(returnedValues).toEqual([0, 0]);
|
|
67
|
-
rerender(createElement(StrictMode, null, createElement(ObservableComponent, { count: 1 })));
|
|
68
|
-
expect(returnedValues).toEqual([0, 0, 0, 0, 1, 1]);
|
|
69
|
-
}));
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { act, render, renderHook } from '@testing-library/react';
|
|
2
|
-
import {
|
|
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 {
|
|
5
|
+
import { useObservable } from '../useObservable';
|
|
6
6
|
test('should subscribe immediately on component mount and unsubscribe on component unmount', () => {
|
|
7
7
|
let subscribed = false;
|
|
8
8
|
const observable = new Observable(() => {
|
package/dist/es2015/index.d.ts
CHANGED
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export { observeState as state, observeCallback as handler, observeContext as context, observeElement as elementRef, } from './utils';
|
|
4
|
-
export { observableCallback } from 'observable-callback';
|
|
5
|
-
export { useObservable, useMemoObservable } from './useObservable';
|
|
6
|
-
export { useAsObservable } from './useAsObservable';
|
|
7
|
-
export { useObservableCallback } from './useObservableCallback';
|
|
1
|
+
export * from './useObservable';
|
|
2
|
+
export * from './useObservableEvent';
|
package/dist/es2015/index.js
CHANGED
|
@@ -1,9 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export { observeState, observeCallback, observeContext, observeElement } from './utils';
|
|
4
|
-
export { observeState as state, observeCallback as handler, observeContext as context, observeElement as elementRef, } from './utils';
|
|
5
|
-
export { observableCallback } from 'observable-callback';
|
|
6
|
-
// hooks
|
|
7
|
-
export { useObservable, useMemoObservable } from './useObservable';
|
|
8
|
-
export { useAsObservable } from './useAsObservable';
|
|
9
|
-
export { useObservableCallback } from './useObservableCallback';
|
|
1
|
+
export * from './useObservable';
|
|
2
|
+
export * from './useObservableEvent';
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
|
-
import { DependencyList } from 'react';
|
|
3
2
|
export declare function useObservable<T>(observable: Observable<T>): T | undefined;
|
|
4
3
|
export declare function useObservable<T>(observable: Observable<T>, initialValue: T): T;
|
|
5
4
|
export declare function useObservable<T>(observable: Observable<T>, initialValue: () => T): T;
|
|
6
|
-
export declare function useMemoObservable<T>(observableOrFactory: Observable<T> | (() => Observable<T>), deps: DependencyList): T | undefined;
|
|
7
|
-
export declare function useMemoObservable<T>(observableOrFactory: Observable<T> | (() => Observable<T>), deps: DependencyList, initialValue: T | (() => T)): T;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { useEffect, useMemo, useRef } from 'react';
|
|
2
|
-
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
1
|
+
import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';
|
|
3
2
|
import { shareReplay, tap } from 'rxjs/operators';
|
|
4
3
|
function getValue(value) {
|
|
5
4
|
return typeof value === 'function' ? value() : value;
|
|
@@ -16,8 +15,19 @@ function getOrCreateStore(inputObservable, initialValue) {
|
|
|
16
15
|
return cache.get(inputObservable);
|
|
17
16
|
}
|
|
18
17
|
export function useObservable(observable, initialValue) {
|
|
18
|
+
/**
|
|
19
|
+
* Store the initialValue in a ref, as we don't want a changed `initialValue` to trigger a re-subscription.
|
|
20
|
+
* But we also don't want the initialValue to be stale if the observable changes.
|
|
21
|
+
*/
|
|
22
|
+
const initialValueRef = useRef(getValue(initialValue));
|
|
23
|
+
/**
|
|
24
|
+
* Ensures that the initialValue is always up-to-date in case the observable changes.
|
|
25
|
+
*/
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
initialValueRef.current = getValue(initialValue);
|
|
28
|
+
}, [initialValue]);
|
|
19
29
|
const [getSnapshot, subscribe] = useMemo(() => {
|
|
20
|
-
const store = getOrCreateStore(observable,
|
|
30
|
+
const store = getOrCreateStore(observable, initialValueRef.current);
|
|
21
31
|
if (store.subscription.closed) {
|
|
22
32
|
store.subscription = store.observable.subscribe();
|
|
23
33
|
}
|
|
@@ -37,7 +47,7 @@ export function useObservable(observable, initialValue) {
|
|
|
37
47
|
}, [observable]);
|
|
38
48
|
const shouldRestoreSubscriptionRef = useRef(false);
|
|
39
49
|
useEffect(() => {
|
|
40
|
-
const store = getOrCreateStore(observable,
|
|
50
|
+
const store = getOrCreateStore(observable, initialValueRef.current);
|
|
41
51
|
if (shouldRestoreSubscriptionRef.current) {
|
|
42
52
|
if (store.subscription.closed) {
|
|
43
53
|
store.subscription = store.observable.subscribe();
|
|
@@ -53,6 +63,3 @@ export function useObservable(observable, initialValue) {
|
|
|
53
63
|
}, [observable]);
|
|
54
64
|
return useSyncExternalStore(subscribe, getSnapshot);
|
|
55
65
|
}
|
|
56
|
-
export function useMemoObservable(observableOrFactory, deps, initialValue) {
|
|
57
|
-
return useObservable(useMemo(() => getValue(observableOrFactory), deps), initialValue);
|
|
58
|
-
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef } from 'react';
|
|
2
1
|
import { observableCallback } from 'observable-callback';
|
|
2
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
3
3
|
const EMPTY_DEPS = [];
|
|
4
4
|
export function useObservableCallback(fn, dependencies = EMPTY_DEPS) {
|
|
5
5
|
const callbackRef = useRef();
|
|
@@ -7,7 +7,6 @@ export function useObservableCallback(fn, dependencies = EMPTY_DEPS) {
|
|
|
7
7
|
callbackRef.current = observableCallback();
|
|
8
8
|
}
|
|
9
9
|
const [calls$, call] = callbackRef.current;
|
|
10
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11
10
|
const callback = useCallback(fn, dependencies);
|
|
12
11
|
useEffect(() => {
|
|
13
12
|
const subscription = calls$.pipe(callback).subscribe();
|
|
@@ -34,11 +34,10 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
34
34
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
|
+
import { act, render } from '@testing-library/react';
|
|
38
|
+
import { createElement, Fragment, StrictMode, useEffect } from 'react';
|
|
37
39
|
import { BehaviorSubject, Observable } from 'rxjs';
|
|
38
40
|
import { useObservable } from '../useObservable';
|
|
39
|
-
import { createElement, Fragment, StrictMode, useEffect } from 'react';
|
|
40
|
-
import { act, render } from '@testing-library/react';
|
|
41
|
-
import { useAsObservable } from '../useAsObservable';
|
|
42
41
|
var wait = function (ms) { return new Promise(function (resolve) { return setTimeout(resolve, ms); }); };
|
|
43
42
|
// NOTE: Jest runs NODE_ENV=test by default, which enables development flags for React
|
|
44
43
|
test('Strict mode should trigger double mount effects and re-renders', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
@@ -50,7 +49,7 @@ test('Strict mode should trigger double mount effects and re-renders', function
|
|
|
50
49
|
returnedValues.push(observedValue);
|
|
51
50
|
return createElement(Fragment, null, observedValue);
|
|
52
51
|
}
|
|
53
|
-
var subject, observable, returnedValues, mountCount
|
|
52
|
+
var subject, observable, returnedValues, mountCount;
|
|
54
53
|
return __generator(this, function (_a) {
|
|
55
54
|
switch (_a.label) {
|
|
56
55
|
case 0:
|
|
@@ -58,7 +57,7 @@ test('Strict mode should trigger double mount effects and re-renders', function
|
|
|
58
57
|
observable = subject.asObservable();
|
|
59
58
|
returnedValues = [];
|
|
60
59
|
mountCount = 0;
|
|
61
|
-
|
|
60
|
+
render(createElement(StrictMode, null, createElement(ObservableComponent)));
|
|
62
61
|
expect(mountCount).toEqual(2);
|
|
63
62
|
expect(returnedValues).toEqual([0, 0]);
|
|
64
63
|
return [4 /*yield*/, wait(10)];
|
|
@@ -74,11 +73,14 @@ test('Strict mode should trigger double mount effects and re-renders', function
|
|
|
74
73
|
});
|
|
75
74
|
}); });
|
|
76
75
|
test('Strict mode should unsubscribe the source observable on unmount', function () {
|
|
77
|
-
var subscribed =
|
|
76
|
+
var subscribed = [];
|
|
77
|
+
var unsubscribed = [];
|
|
78
|
+
var nextId = 0;
|
|
78
79
|
var observable = new Observable(function () {
|
|
79
|
-
|
|
80
|
+
var id = nextId++;
|
|
81
|
+
subscribed.push(id);
|
|
80
82
|
return function () {
|
|
81
|
-
|
|
83
|
+
unsubscribed.push(id);
|
|
82
84
|
};
|
|
83
85
|
});
|
|
84
86
|
function ObservableComponent() {
|
|
@@ -86,24 +88,7 @@ test('Strict mode should unsubscribe the source observable on unmount', function
|
|
|
86
88
|
return createElement(Fragment, null);
|
|
87
89
|
}
|
|
88
90
|
var rerender = render(createElement(StrictMode, null, createElement(ObservableComponent))).rerender;
|
|
89
|
-
expect(subscribed).
|
|
91
|
+
expect(subscribed).toEqual([0, 1]);
|
|
90
92
|
rerender(createElement(StrictMode, null, createElement('div')));
|
|
91
|
-
expect(
|
|
93
|
+
expect(unsubscribed).toEqual([0, 1]);
|
|
92
94
|
});
|
|
93
|
-
test('useAsObservable should work in strict mode', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
94
|
-
function ObservableComponent(props) {
|
|
95
|
-
var count$ = useAsObservable(props.count);
|
|
96
|
-
var count = useObservable(count$);
|
|
97
|
-
returnedValues.push(count);
|
|
98
|
-
return createElement(Fragment, null, 'ok');
|
|
99
|
-
}
|
|
100
|
-
var returnedValues, rerender;
|
|
101
|
-
return __generator(this, function (_a) {
|
|
102
|
-
returnedValues = [];
|
|
103
|
-
rerender = render(createElement(StrictMode, null, createElement(ObservableComponent, { count: 0 }))).rerender;
|
|
104
|
-
expect(returnedValues).toEqual([0, 0]);
|
|
105
|
-
rerender(createElement(StrictMode, null, createElement(ObservableComponent, { count: 1 })));
|
|
106
|
-
expect(returnedValues).toEqual([0, 0, 0, 0, 1, 1]);
|
|
107
|
-
return [2 /*return*/];
|
|
108
|
-
});
|
|
109
|
-
}); });
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { act, render, renderHook } from '@testing-library/react';
|
|
2
|
-
import {
|
|
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 {
|
|
5
|
+
import { useObservable } from '../useObservable';
|
|
6
6
|
test('should subscribe immediately on component mount and unsubscribe on component unmount', function () {
|
|
7
7
|
var subscribed = false;
|
|
8
8
|
var observable = new Observable(function () {
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export { observeState as state, observeCallback as handler, observeContext as context, observeElement as elementRef, } from './utils';
|
|
4
|
-
export { observableCallback } from 'observable-callback';
|
|
5
|
-
export { useObservable, useMemoObservable } from './useObservable';
|
|
6
|
-
export { useAsObservable } from './useAsObservable';
|
|
7
|
-
export { useObservableCallback } from './useObservableCallback';
|
|
1
|
+
export * from './useObservable';
|
|
2
|
+
export * from './useObservableEvent';
|
package/dist/esm/index.js
CHANGED
|
@@ -1,9 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export { observeState, observeCallback, observeContext, observeElement } from './utils';
|
|
4
|
-
export { observeState as state, observeCallback as handler, observeContext as context, observeElement as elementRef, } from './utils';
|
|
5
|
-
export { observableCallback } from 'observable-callback';
|
|
6
|
-
// hooks
|
|
7
|
-
export { useObservable, useMemoObservable } from './useObservable';
|
|
8
|
-
export { useAsObservable } from './useAsObservable';
|
|
9
|
-
export { useObservableCallback } from './useObservableCallback';
|
|
1
|
+
export * from './useObservable';
|
|
2
|
+
export * from './useObservableEvent';
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
|
-
import { DependencyList } from 'react';
|
|
3
2
|
export declare function useObservable<T>(observable: Observable<T>): T | undefined;
|
|
4
3
|
export declare function useObservable<T>(observable: Observable<T>, initialValue: T): T;
|
|
5
4
|
export declare function useObservable<T>(observable: Observable<T>, initialValue: () => T): T;
|
|
6
|
-
export declare function useMemoObservable<T>(observableOrFactory: Observable<T> | (() => Observable<T>), deps: DependencyList): T | undefined;
|
|
7
|
-
export declare function useMemoObservable<T>(observableOrFactory: Observable<T> | (() => Observable<T>), deps: DependencyList, initialValue: T | (() => T)): T;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { useEffect, useMemo, useRef } from 'react';
|
|
2
|
-
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
1
|
+
import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';
|
|
3
2
|
import { shareReplay, tap } from 'rxjs/operators';
|
|
4
3
|
function getValue(value) {
|
|
5
4
|
return typeof value === 'function' ? value() : value;
|
|
@@ -16,8 +15,19 @@ function getOrCreateStore(inputObservable, initialValue) {
|
|
|
16
15
|
return cache.get(inputObservable);
|
|
17
16
|
}
|
|
18
17
|
export function useObservable(observable, initialValue) {
|
|
18
|
+
/**
|
|
19
|
+
* Store the initialValue in a ref, as we don't want a changed `initialValue` to trigger a re-subscription.
|
|
20
|
+
* But we also don't want the initialValue to be stale if the observable changes.
|
|
21
|
+
*/
|
|
22
|
+
var initialValueRef = useRef(getValue(initialValue));
|
|
23
|
+
/**
|
|
24
|
+
* Ensures that the initialValue is always up-to-date in case the observable changes.
|
|
25
|
+
*/
|
|
26
|
+
useEffect(function () {
|
|
27
|
+
initialValueRef.current = getValue(initialValue);
|
|
28
|
+
}, [initialValue]);
|
|
19
29
|
var _a = useMemo(function () {
|
|
20
|
-
var store = getOrCreateStore(observable,
|
|
30
|
+
var store = getOrCreateStore(observable, initialValueRef.current);
|
|
21
31
|
if (store.subscription.closed) {
|
|
22
32
|
store.subscription = store.observable.subscribe();
|
|
23
33
|
}
|
|
@@ -37,7 +47,7 @@ export function useObservable(observable, initialValue) {
|
|
|
37
47
|
}, [observable]), getSnapshot = _a[0], subscribe = _a[1];
|
|
38
48
|
var shouldRestoreSubscriptionRef = useRef(false);
|
|
39
49
|
useEffect(function () {
|
|
40
|
-
var store = getOrCreateStore(observable,
|
|
50
|
+
var store = getOrCreateStore(observable, initialValueRef.current);
|
|
41
51
|
if (shouldRestoreSubscriptionRef.current) {
|
|
42
52
|
if (store.subscription.closed) {
|
|
43
53
|
store.subscription = store.observable.subscribe();
|
|
@@ -53,6 +63,3 @@ export function useObservable(observable, initialValue) {
|
|
|
53
63
|
}, [observable]);
|
|
54
64
|
return useSyncExternalStore(subscribe, getSnapshot);
|
|
55
65
|
}
|
|
56
|
-
export function useMemoObservable(observableOrFactory, deps, initialValue) {
|
|
57
|
-
return useObservable(useMemo(function () { return getValue(observableOrFactory); }, deps), initialValue);
|
|
58
|
-
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef } from 'react';
|
|
2
1
|
import { observableCallback } from 'observable-callback';
|
|
2
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
3
3
|
var EMPTY_DEPS = [];
|
|
4
4
|
export function useObservableCallback(fn, dependencies) {
|
|
5
5
|
if (dependencies === void 0) { dependencies = EMPTY_DEPS; }
|
|
@@ -8,7 +8,6 @@ export function useObservableCallback(fn, dependencies) {
|
|
|
8
8
|
callbackRef.current = observableCallback();
|
|
9
9
|
}
|
|
10
10
|
var _a = callbackRef.current, calls$ = _a[0], call = _a[1];
|
|
11
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
12
11
|
var callback = useCallback(fn, dependencies);
|
|
13
12
|
useEffect(function () {
|
|
14
13
|
var subscription = calls$.pipe(callback).subscribe();
|