react-rx 1.0.0 → 2.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/.idea/compiler.xml +1 -1
- package/.idea/inspectionProfiles/Project_Default.xml +1 -0
- package/.idea/markdown.xml +9 -0
- package/.idea/misc.xml +0 -6
- package/dist/cjs/displayName.js +1 -1
- package/dist/cjs/useAsObservable.js +9 -17
- package/dist/cjs/useObservable.js +25 -30
- package/dist/cjs/withPropsStream.js +5 -1
- package/dist/es2015/useAsObservable.js +10 -18
- package/dist/es2015/useObservable.js +24 -31
- package/dist/esm/displayName.js +1 -1
- package/dist/esm/useAsObservable.js +10 -18
- package/dist/esm/useObservable.js +26 -31
- package/package.json +6 -4
- package/src/useAsObservable.ts +13 -18
- package/src/useObservable.ts +39 -34
- package/.idea/workspace.xml +0 -226
- package/jest.config.js +0 -5
- package/website/.babelrc +0 -21
- package/website/.prettierrc +0 -7
- package/website/README.mdx +0 -1
- package/website/package.json +0 -84
- package/website/src/@types/babel.d.ts +0 -4
- package/website/src/@types/mdx.d.ts +0 -11
- package/website/src/@types/react-css-burger.d.ts +0 -4
- package/website/src/App.tsx +0 -68
- package/website/src/components/Header.tsx +0 -118
- package/website/src/components/Link.tsx +0 -18
- package/website/src/components/LoadPage.tsx +0 -60
- package/website/src/components/Sidebar.tsx +0 -88
- package/website/src/components/logos/Github.tsx +0 -10
- package/website/src/components/logos/React.tsx +0 -27
- package/website/src/components/logos/ReactRxLogo.tsx +0 -39
- package/website/src/components/logos/RxJs.tsx +0 -69
- package/website/src/components/repl/Checkerboard.tsx +0 -25
- package/website/src/components/repl/CodeBlock.tsx +0 -147
- package/website/src/components/repl/CodeMirror.tsx +0 -37
- package/website/src/components/repl/CodeMirrorMode.tsx +0 -67
- package/website/src/components/repl/EvalCode.tsx +0 -55
- package/website/src/components/repl/Prelude.tsx +0 -50
- package/website/src/components/repl/ShowError.tsx +0 -27
- package/website/src/components/repl/codemirror-lib.ts +0 -8
- package/website/src/components/repl/codemirror-theme.css +0 -131
- package/website/src/components/repl/compile/babel.ts +0 -21
- package/website/src/components/repl/eval/evalCallback.ts +0 -27
- package/website/src/components/repl/eval/evalCode.ts +0 -7
- package/website/src/components/repl/eval/evalExpression.ts +0 -4
- package/website/src/components/repl/eval/evalReactDomRender.ts +0 -23
- package/website/src/components/repl/index.ts +0 -1
- package/website/src/components/repl/runMode.ts +0 -42
- package/website/src/datastores/location.ts +0 -14
- package/website/src/datastores/page.ts +0 -11
- package/website/src/datastores/pageTransition.ts +0 -97
- package/website/src/entries/main.css +0 -2
- package/website/src/entries/main.tsx +0 -6
- package/website/src/examples/FizzBuzz/FizzBuzzExample.tsx +0 -39
- package/website/src/examples/FizzBuzz/index.tsx +0 -9
- package/website/src/examples/_utils/globalScope.ts +0 -45
- package/website/src/examples/animation/AnimationExample.tsx +0 -152
- package/website/src/examples/animation/easings.ts +0 -0
- package/website/src/examples/animation/index.tsx +0 -15
- package/website/src/examples/context/Context.example.jsx +0 -67
- package/website/src/examples/context/index.tsx +0 -9
- package/website/src/examples/errors/Errors.example.jsx +0 -69
- package/website/src/examples/errors/index.tsx +0 -9
- package/website/src/examples/event-handlers/EventHandlersExample.tsx +0 -48
- package/website/src/examples/event-handlers/index.tsx +0 -9
- package/website/src/examples/fetch/FetchExample.jsx +0 -43
- package/website/src/examples/fetch/a.txt +0 -1
- package/website/src/examples/fetch/b.txt +0 -1
- package/website/src/examples/fetch/index.tsx +0 -9
- package/website/src/examples/form-data/FormDataExample.jsx +0 -119
- package/website/src/examples/form-data/index.tsx +0 -12
- package/website/src/examples/form-data/storage.ts +0 -27
- package/website/src/examples/forward-ref/ForwardRefExample.tsx +0 -55
- package/website/src/examples/forward-ref/index.tsx +0 -9
- package/website/src/examples/hello-world/HelloWorld.example.jsx +0 -6
- package/website/src/examples/hello-world/index.tsx +0 -9
- package/website/src/examples/hooks-interop/HooksInterop.example.tsx +0 -42
- package/website/src/examples/hooks-interop/index.tsx +0 -9
- package/website/src/examples/passthrough-props/PassThroughPropsExample.jsx +0 -57
- package/website/src/examples/passthrough-props/index.tsx +0 -11
- package/website/src/examples/reactive-state/ReactiveState.example.jsx +0 -43
- package/website/src/examples/reactive-state/index.ts +0 -9
- package/website/src/examples/readme-examples/README.mdx +0 -0
- package/website/src/examples/readme-examples/index.ts +0 -11
- package/website/src/examples/shared-state/SharedState.example.tsx +0 -59
- package/website/src/examples/shared-state/index.tsx +0 -9
- package/website/src/examples/simple/Counter.example.tsx +0 -14
- package/website/src/examples/simple/index.tsx +0 -9
- package/website/src/examples/sync/Sync.example.tsx +0 -9
- package/website/src/examples/sync/index.tsx +0 -9
- package/website/src/examples/tick/TickExample.jsx +0 -51
- package/website/src/examples/tick/index.ts +0 -9
- package/website/src/examples/todo-app/TodoApp.example.tsx +0 -88
- package/website/src/examples/todo-app/index.tsx +0 -12
- package/website/src/examples/todo-app/storage.ts +0 -27
- package/website/src/examples/use-element/UseElementExample.tsx +0 -70
- package/website/src/examples/use-element/index.tsx +0 -9
- package/website/src/examples/use-observable/search/SearchExample.tsx +0 -82
- package/website/src/examples/use-observable/search/index.tsx +0 -8
- package/website/src/examples/use-observable/use-observable/UseObservableExample.tsx +0 -70
- package/website/src/examples/use-observable/use-observable/index.tsx +0 -9
- package/website/src/index.html +0 -10
- package/website/src/mdx-components.tsx +0 -74
- package/website/src/pages/Api/Api.mdx +0 -134
- package/website/src/pages/Api/ApiPage.tsx +0 -25
- package/website/src/pages/Examples/Examples.tsx +0 -105
- package/website/src/pages/Examples/ExamplesPage.tsx +0 -13
- package/website/src/pages/Guide/Guide.mdx +0 -275
- package/website/src/pages/Guide/GuidePage.tsx +0 -25
- package/website/src/pages/Index/IndexPage.tsx +0 -50
- package/website/src/pages/Index/ReactRxReadme.md +0 -20
- package/website/src/pages/NotFound.tsx +0 -3
- package/website/src/pages/pages.ts +0 -46
- package/website/src/pages/styles.tsx +0 -24
- package/website/src/theme.ts +0 -61
- package/website/src/utils/parseCodeFenceHeader.ts +0 -32
- package/website/tsconfig.json +0 -30
- package/website/vercel.json +0 -4
- package/website/webpack/config.js +0 -5
- package/website/webpack/createConfig.js +0 -95
- package/website/webpack/mdx-toc-loader.js +0 -38
package/.idea/compiler.xml
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<component name="InspectionProjectProfileManager">
|
|
2
2
|
<profile version="1.0">
|
|
3
3
|
<option name="myName" value="Project Default" />
|
|
4
|
+
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
|
4
5
|
<inspection_tool class="TypescriptExplicitMemberType" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
|
5
6
|
</profile>
|
|
6
7
|
</component>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="MarkdownSettings">
|
|
4
|
+
<enabledExtensions>
|
|
5
|
+
<entry key="MermaidLanguageExtension" value="false" />
|
|
6
|
+
<entry key="PlantUMLLanguageExtension" value="false" />
|
|
7
|
+
</enabledExtensions>
|
|
8
|
+
</component>
|
|
9
|
+
</project>
|
package/.idea/misc.xml
CHANGED
package/dist/cjs/displayName.js
CHANGED
|
@@ -8,6 +8,6 @@ var getDisplayName = function (Component) {
|
|
|
8
8
|
return (Component && (Component.displayName || Component.name)) || 'Unknown';
|
|
9
9
|
};
|
|
10
10
|
var wrapDisplayName = function (BaseComponent, wrapperName) {
|
|
11
|
-
return wrapperName
|
|
11
|
+
return "".concat(wrapperName, "(").concat(getDisplayName(BaseComponent), ")");
|
|
12
12
|
};
|
|
13
13
|
exports.wrapDisplayName = wrapDisplayName;
|
|
@@ -5,27 +5,19 @@ var rxjs_1 = require("rxjs");
|
|
|
5
5
|
var react_1 = require("react");
|
|
6
6
|
var useIsomorphicEffect_1 = require("./useIsomorphicEffect");
|
|
7
7
|
function useAsObservable(value, operator) {
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
observableRef.current = operator ? observable.pipe(operator) : observable;
|
|
14
|
-
}
|
|
8
|
+
var _a = (0, react_1.useMemo)(function () {
|
|
9
|
+
var subject = new rxjs_1.BehaviorSubject(value);
|
|
10
|
+
var observable = subject.asObservable();
|
|
11
|
+
return [operator ? observable.pipe(operator) : observable, subject];
|
|
12
|
+
}, []), observable = _a[0], subject = _a[1];
|
|
15
13
|
(0, useIsomorphicEffect_1.useIsomorphicEffect)(function () {
|
|
16
|
-
|
|
17
|
-
isInitial.current = false;
|
|
18
|
-
}
|
|
19
|
-
else {
|
|
20
|
-
// emit only on update
|
|
21
|
-
subjectRef.current.next(value);
|
|
22
|
-
}
|
|
14
|
+
subject.next(value);
|
|
23
15
|
}, [value]);
|
|
24
|
-
(0,
|
|
16
|
+
(0, react_1.useEffect)(function () {
|
|
25
17
|
return function () {
|
|
26
|
-
|
|
18
|
+
subject.complete();
|
|
27
19
|
};
|
|
28
20
|
}, []);
|
|
29
|
-
return
|
|
21
|
+
return observable;
|
|
30
22
|
}
|
|
31
23
|
exports.useAsObservable = useAsObservable;
|
|
@@ -1,42 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useMemoObservable = exports.useObservable = void 0;
|
|
4
|
+
var rxjs_1 = require("rxjs");
|
|
4
5
|
var react_1 = require("react");
|
|
5
|
-
var
|
|
6
|
+
var useAsObservable_1 = require("./useAsObservable");
|
|
7
|
+
var operators_1 = require("rxjs/operators");
|
|
8
|
+
var shim_1 = require("use-sync-external-store/shim");
|
|
6
9
|
function getValue(value) {
|
|
7
10
|
return typeof value === 'function' ? value() : value;
|
|
8
11
|
}
|
|
9
|
-
function
|
|
10
|
-
var
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return syncVal;
|
|
25
|
-
}), value = _a[0], setState = _a[1];
|
|
26
|
-
(0, useIsomorphicEffect_1.useIsomorphicEffect)(function () {
|
|
27
|
-
// when the observable changes after initial (possibly sync render)
|
|
28
|
-
if (!isInitial.current) {
|
|
29
|
-
subscription.current = observable.subscribe(function (nextVal) { return setState(nextVal); });
|
|
30
|
-
}
|
|
31
|
-
isInitial.current = false;
|
|
32
|
-
return function () {
|
|
33
|
-
if (subscription.current) {
|
|
34
|
-
subscription.current.unsubscribe();
|
|
35
|
-
subscription.current = undefined;
|
|
36
|
-
}
|
|
12
|
+
function useObservableSubscription(observable) {
|
|
13
|
+
var store = (0, react_1.useMemo)(function () {
|
|
14
|
+
var currentValue;
|
|
15
|
+
return {
|
|
16
|
+
// Note: this works because the given observable always emits a value synchronously by concat-ing the given initialValue
|
|
17
|
+
getCurrentValue: function () { return currentValue; },
|
|
18
|
+
subscribe: function (callback) {
|
|
19
|
+
var subscription = observable.subscribe(function (value) {
|
|
20
|
+
currentValue = value;
|
|
21
|
+
callback(value);
|
|
22
|
+
});
|
|
23
|
+
return function () {
|
|
24
|
+
subscription.unsubscribe();
|
|
25
|
+
};
|
|
26
|
+
},
|
|
37
27
|
};
|
|
38
28
|
}, [observable]);
|
|
39
|
-
return
|
|
29
|
+
return (0, shim_1.useSyncExternalStore)(store.subscribe, store.getCurrentValue);
|
|
30
|
+
}
|
|
31
|
+
function useObservable(observable, initialValue) {
|
|
32
|
+
return useObservableSubscription((0, useAsObservable_1.useAsObservable)(observable, (0, rxjs_1.pipe)((0, operators_1.distinctUntilChanged)(), (0, operators_1.switchMap)(function (observable) {
|
|
33
|
+
return (0, rxjs_1.merge)((0, rxjs_1.defer)(function () { return (0, rxjs_1.of)(getValue(initialValue)); }), observable);
|
|
34
|
+
}))));
|
|
40
35
|
}
|
|
41
36
|
exports.useObservable = useObservable;
|
|
42
37
|
function useMemoObservable(observableOrFactory, deps, initialValue) {
|
|
@@ -12,7 +12,11 @@ var __assign = (this && this.__assign) || function () {
|
|
|
12
12
|
};
|
|
13
13
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
14
|
if (k2 === undefined) k2 = k;
|
|
15
|
-
Object.
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
16
20
|
}) : (function(o, m, k, k2) {
|
|
17
21
|
if (k2 === undefined) k2 = k;
|
|
18
22
|
o[k2] = m[k];
|
|
@@ -1,27 +1,19 @@
|
|
|
1
1
|
import { BehaviorSubject } from 'rxjs';
|
|
2
|
-
import {
|
|
2
|
+
import { useEffect, useMemo } from 'react';
|
|
3
3
|
import { useIsomorphicEffect } from './useIsomorphicEffect';
|
|
4
4
|
export function useAsObservable(value, operator) {
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
observableRef.current = operator ? observable.pipe(operator) : observable;
|
|
11
|
-
}
|
|
5
|
+
const [observable, subject] = useMemo(() => {
|
|
6
|
+
const subject = new BehaviorSubject(value);
|
|
7
|
+
const observable = subject.asObservable();
|
|
8
|
+
return [operator ? observable.pipe(operator) : observable, subject];
|
|
9
|
+
}, []);
|
|
12
10
|
useIsomorphicEffect(() => {
|
|
13
|
-
|
|
14
|
-
isInitial.current = false;
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
// emit only on update
|
|
18
|
-
subjectRef.current.next(value);
|
|
19
|
-
}
|
|
11
|
+
subject.next(value);
|
|
20
12
|
}, [value]);
|
|
21
|
-
|
|
13
|
+
useEffect(() => {
|
|
22
14
|
return () => {
|
|
23
|
-
|
|
15
|
+
subject.complete();
|
|
24
16
|
};
|
|
25
17
|
}, []);
|
|
26
|
-
return
|
|
18
|
+
return observable;
|
|
27
19
|
}
|
|
@@ -1,39 +1,32 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { defer, merge, of, pipe } from 'rxjs';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { useAsObservable } from './useAsObservable';
|
|
4
|
+
import { distinctUntilChanged, switchMap } from 'rxjs/operators';
|
|
5
|
+
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
3
6
|
function getValue(value) {
|
|
4
7
|
return typeof value === 'function' ? value() : value;
|
|
5
8
|
}
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return syncVal;
|
|
22
|
-
});
|
|
23
|
-
useIsomorphicEffect(() => {
|
|
24
|
-
// when the observable changes after initial (possibly sync render)
|
|
25
|
-
if (!isInitial.current) {
|
|
26
|
-
subscription.current = observable.subscribe(nextVal => setState(nextVal));
|
|
27
|
-
}
|
|
28
|
-
isInitial.current = false;
|
|
29
|
-
return () => {
|
|
30
|
-
if (subscription.current) {
|
|
31
|
-
subscription.current.unsubscribe();
|
|
32
|
-
subscription.current = undefined;
|
|
33
|
-
}
|
|
9
|
+
function useObservableSubscription(observable) {
|
|
10
|
+
const store = useMemo(() => {
|
|
11
|
+
let currentValue;
|
|
12
|
+
return {
|
|
13
|
+
// Note: this works because the given observable always emits a value synchronously by concat-ing the given initialValue
|
|
14
|
+
getCurrentValue: () => currentValue,
|
|
15
|
+
subscribe: (callback) => {
|
|
16
|
+
const subscription = observable.subscribe(value => {
|
|
17
|
+
currentValue = value;
|
|
18
|
+
callback(value);
|
|
19
|
+
});
|
|
20
|
+
return () => {
|
|
21
|
+
subscription.unsubscribe();
|
|
22
|
+
};
|
|
23
|
+
},
|
|
34
24
|
};
|
|
35
25
|
}, [observable]);
|
|
36
|
-
return
|
|
26
|
+
return useSyncExternalStore(store.subscribe, store.getCurrentValue);
|
|
27
|
+
}
|
|
28
|
+
export function useObservable(observable, initialValue) {
|
|
29
|
+
return useObservableSubscription(useAsObservable(observable, pipe(distinctUntilChanged(), switchMap(observable => merge(defer(() => of(getValue(initialValue))), observable)))));
|
|
37
30
|
}
|
|
38
31
|
export function useMemoObservable(observableOrFactory, deps, initialValue) {
|
|
39
32
|
return useObservable(useMemo(() => getValue(observableOrFactory), deps), initialValue);
|
package/dist/esm/displayName.js
CHANGED
|
@@ -5,5 +5,5 @@ var getDisplayName = function (Component) {
|
|
|
5
5
|
return (Component && (Component.displayName || Component.name)) || 'Unknown';
|
|
6
6
|
};
|
|
7
7
|
export var wrapDisplayName = function (BaseComponent, wrapperName) {
|
|
8
|
-
return wrapperName
|
|
8
|
+
return "".concat(wrapperName, "(").concat(getDisplayName(BaseComponent), ")");
|
|
9
9
|
};
|
|
@@ -1,27 +1,19 @@
|
|
|
1
1
|
import { BehaviorSubject } from 'rxjs';
|
|
2
|
-
import {
|
|
2
|
+
import { useEffect, useMemo } from 'react';
|
|
3
3
|
import { useIsomorphicEffect } from './useIsomorphicEffect';
|
|
4
4
|
export function useAsObservable(value, operator) {
|
|
5
|
-
var
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
observableRef.current = operator ? observable.pipe(operator) : observable;
|
|
11
|
-
}
|
|
5
|
+
var _a = useMemo(function () {
|
|
6
|
+
var subject = new BehaviorSubject(value);
|
|
7
|
+
var observable = subject.asObservable();
|
|
8
|
+
return [operator ? observable.pipe(operator) : observable, subject];
|
|
9
|
+
}, []), observable = _a[0], subject = _a[1];
|
|
12
10
|
useIsomorphicEffect(function () {
|
|
13
|
-
|
|
14
|
-
isInitial.current = false;
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
// emit only on update
|
|
18
|
-
subjectRef.current.next(value);
|
|
19
|
-
}
|
|
11
|
+
subject.next(value);
|
|
20
12
|
}, [value]);
|
|
21
|
-
|
|
13
|
+
useEffect(function () {
|
|
22
14
|
return function () {
|
|
23
|
-
|
|
15
|
+
subject.complete();
|
|
24
16
|
};
|
|
25
17
|
}, []);
|
|
26
|
-
return
|
|
18
|
+
return observable;
|
|
27
19
|
}
|
|
@@ -1,39 +1,34 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { defer, merge, of, pipe } from 'rxjs';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { useAsObservable } from './useAsObservable';
|
|
4
|
+
import { distinctUntilChanged, switchMap } from 'rxjs/operators';
|
|
5
|
+
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
3
6
|
function getValue(value) {
|
|
4
7
|
return typeof value === 'function' ? value() : value;
|
|
5
8
|
}
|
|
6
|
-
|
|
7
|
-
var
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return syncVal;
|
|
22
|
-
}), value = _a[0], setState = _a[1];
|
|
23
|
-
useIsomorphicEffect(function () {
|
|
24
|
-
// when the observable changes after initial (possibly sync render)
|
|
25
|
-
if (!isInitial.current) {
|
|
26
|
-
subscription.current = observable.subscribe(function (nextVal) { return setState(nextVal); });
|
|
27
|
-
}
|
|
28
|
-
isInitial.current = false;
|
|
29
|
-
return function () {
|
|
30
|
-
if (subscription.current) {
|
|
31
|
-
subscription.current.unsubscribe();
|
|
32
|
-
subscription.current = undefined;
|
|
33
|
-
}
|
|
9
|
+
function useObservableSubscription(observable) {
|
|
10
|
+
var store = useMemo(function () {
|
|
11
|
+
var currentValue;
|
|
12
|
+
return {
|
|
13
|
+
// Note: this works because the given observable always emits a value synchronously by concat-ing the given initialValue
|
|
14
|
+
getCurrentValue: function () { return currentValue; },
|
|
15
|
+
subscribe: function (callback) {
|
|
16
|
+
var subscription = observable.subscribe(function (value) {
|
|
17
|
+
currentValue = value;
|
|
18
|
+
callback(value);
|
|
19
|
+
});
|
|
20
|
+
return function () {
|
|
21
|
+
subscription.unsubscribe();
|
|
22
|
+
};
|
|
23
|
+
},
|
|
34
24
|
};
|
|
35
25
|
}, [observable]);
|
|
36
|
-
return
|
|
26
|
+
return useSyncExternalStore(store.subscribe, store.getCurrentValue);
|
|
27
|
+
}
|
|
28
|
+
export function useObservable(observable, initialValue) {
|
|
29
|
+
return useObservableSubscription(useAsObservable(observable, pipe(distinctUntilChanged(), switchMap(function (observable) {
|
|
30
|
+
return merge(defer(function () { return of(getValue(initialValue)); }), observable);
|
|
31
|
+
}))));
|
|
37
32
|
}
|
|
38
33
|
export function useMemoObservable(observableOrFactory, deps, initialValue) {
|
|
39
34
|
return useObservable(useMemo(function () { return getValue(observableOrFactory); }, deps), initialValue);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-rx",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "React + RxJS = <3",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"types": "dist/cjs/index.d.ts",
|
|
@@ -22,11 +22,12 @@
|
|
|
22
22
|
"author": "Bjørge Næss <bjoerge@gmail.com>",
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"observable-callback": "^1.0.1"
|
|
25
|
+
"observable-callback": "^1.0.1",
|
|
26
|
+
"use-sync-external-store": "^1.2.0"
|
|
26
27
|
},
|
|
27
28
|
"peerDependencies": {
|
|
28
|
-
"react": "
|
|
29
|
-
"rxjs": "^6
|
|
29
|
+
"react": "^16.8 || ^17 || ^18",
|
|
30
|
+
"rxjs": "^6.5 || ^7"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
33
|
"@testing-library/dom": "^7.29.6",
|
|
@@ -35,6 +36,7 @@
|
|
|
35
36
|
"@types/jest": "^26.0.20",
|
|
36
37
|
"@types/react": "^17.0.2",
|
|
37
38
|
"@types/react-dom": "^17.0.1",
|
|
39
|
+
"@types/use-sync-external-store": "^0.0.3",
|
|
38
40
|
"@typescript-eslint/eslint-plugin": "^4.15.2",
|
|
39
41
|
"@typescript-eslint/parser": "^4.15.2",
|
|
40
42
|
"eslint": "^7.21.0",
|
package/src/useAsObservable.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {BehaviorSubject, Observable
|
|
2
|
-
import {
|
|
1
|
+
import {BehaviorSubject, Observable} from 'rxjs'
|
|
2
|
+
import {useEffect, useMemo} from 'react'
|
|
3
3
|
import {useIsomorphicEffect} from './useIsomorphicEffect'
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -17,27 +17,22 @@ export function useAsObservable<T, K = T>(
|
|
|
17
17
|
value: T,
|
|
18
18
|
operator?: (input: Observable<T>) => Observable<K>,
|
|
19
19
|
): Observable<T | K> {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
20
|
+
const [observable, subject] = useMemo(() => {
|
|
21
|
+
const subject = new BehaviorSubject(value)
|
|
22
|
+
|
|
23
|
+
const observable = subject.asObservable()
|
|
24
|
+
return [operator ? observable.pipe(operator) : observable, subject]
|
|
25
|
+
}, [])
|
|
27
26
|
|
|
28
27
|
useIsomorphicEffect(() => {
|
|
29
|
-
|
|
30
|
-
isInitial.current = false
|
|
31
|
-
} else {
|
|
32
|
-
// emit only on update
|
|
33
|
-
subjectRef.current.next(value)
|
|
34
|
-
}
|
|
28
|
+
subject.next(value)
|
|
35
29
|
}, [value])
|
|
36
|
-
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
37
32
|
return () => {
|
|
38
|
-
|
|
33
|
+
subject.complete()
|
|
39
34
|
}
|
|
40
35
|
}, [])
|
|
41
36
|
|
|
42
|
-
return
|
|
37
|
+
return observable
|
|
43
38
|
}
|
package/src/useObservable.ts
CHANGED
|
@@ -1,46 +1,51 @@
|
|
|
1
|
-
import {Observable,
|
|
2
|
-
import {DependencyList, useMemo
|
|
3
|
-
import {
|
|
1
|
+
import {defer, merge, Observable, of, pipe} from 'rxjs'
|
|
2
|
+
import {DependencyList, useMemo} from 'react'
|
|
3
|
+
import {useAsObservable} from './useAsObservable'
|
|
4
|
+
import {distinctUntilChanged, switchMap} from 'rxjs/operators'
|
|
5
|
+
import {useSyncExternalStore} from 'use-sync-external-store/shim'
|
|
4
6
|
|
|
5
7
|
function getValue<T>(value: T): T extends () => infer U ? U : T {
|
|
6
8
|
return typeof value === 'function' ? value() : value
|
|
7
9
|
}
|
|
8
10
|
|
|
11
|
+
function useObservableSubscription<T>(observable: Observable<T>): T {
|
|
12
|
+
const store = useMemo(() => {
|
|
13
|
+
let currentValue: T
|
|
14
|
+
return {
|
|
15
|
+
// Note: this works because the given observable always emits a value synchronously by concat-ing the given initialValue
|
|
16
|
+
getCurrentValue: () => currentValue,
|
|
17
|
+
subscribe: (callback: (value: T) => void) => {
|
|
18
|
+
const subscription = observable.subscribe(value => {
|
|
19
|
+
currentValue = value
|
|
20
|
+
callback(value)
|
|
21
|
+
})
|
|
22
|
+
return () => {
|
|
23
|
+
subscription.unsubscribe()
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
}, [observable])
|
|
28
|
+
return useSyncExternalStore(store.subscribe, store.getCurrentValue)
|
|
29
|
+
}
|
|
30
|
+
|
|
9
31
|
export function useObservable<T>(observable: Observable<T>): T | undefined
|
|
10
32
|
export function useObservable<T>(observable: Observable<T>, initialValue: T): T
|
|
11
33
|
export function useObservable<T>(observable: Observable<T>, initialValue: () => T): T
|
|
12
34
|
export function useObservable<T>(observable: Observable<T>, initialValue?: T | (() => T)) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
useIsomorphicEffect(() => {
|
|
30
|
-
// when the observable changes after initial (possibly sync render)
|
|
31
|
-
if (!isInitial.current) {
|
|
32
|
-
subscription.current = observable.subscribe(nextVal => setState(nextVal))
|
|
33
|
-
}
|
|
34
|
-
isInitial.current = false
|
|
35
|
-
return () => {
|
|
36
|
-
if (subscription.current) {
|
|
37
|
-
subscription.current.unsubscribe()
|
|
38
|
-
subscription.current = undefined
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}, [observable])
|
|
42
|
-
|
|
43
|
-
return value
|
|
35
|
+
return useObservableSubscription(
|
|
36
|
+
useAsObservable(
|
|
37
|
+
observable,
|
|
38
|
+
pipe(
|
|
39
|
+
distinctUntilChanged(),
|
|
40
|
+
switchMap(observable =>
|
|
41
|
+
merge(
|
|
42
|
+
defer(() => of(getValue(initialValue))),
|
|
43
|
+
observable,
|
|
44
|
+
),
|
|
45
|
+
),
|
|
46
|
+
),
|
|
47
|
+
),
|
|
48
|
+
)
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
export function useMemoObservable<T>(
|