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
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
import { ComponentType, ReactNode } from 'react';
|
|
3
|
-
interface Props<T> {
|
|
4
|
-
observable: Observable<T>;
|
|
5
|
-
children: (value: T) => ReactNode;
|
|
6
|
-
}
|
|
7
|
-
declare type ObservableComponent<T> = ComponentType<Props<T>>;
|
|
8
|
-
/**
|
|
9
|
-
* @deprecated Use the useObservable hook instead
|
|
10
|
-
*/
|
|
11
|
-
export declare const WithObservable: ObservableComponent<unknown>;
|
|
12
|
-
export {};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { distinctUntilChanged, map, switchMap } from 'rxjs/operators';
|
|
2
|
-
import { reactiveComponent } from './reactiveComponent';
|
|
3
|
-
function createWithObservable() {
|
|
4
|
-
return reactiveComponent((props$) => props$.pipe(distinctUntilChanged((props, prevProps) => props.observable === prevProps.observable), switchMap((props) => props.observable.pipe(map((observableValue) => props.children(observableValue))))));
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* @deprecated Use the useObservable hook instead
|
|
8
|
-
*/
|
|
9
|
-
export const WithObservable = createWithObservable();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { useAsObservable } from '../useAsObservable';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import { renderHook } from '@testing-library/react';
|
|
4
|
-
test('the returned observable should receive a new value when component is rendered with a new value', () => {
|
|
5
|
-
const receivedValues = [];
|
|
6
|
-
const { unmount, rerender } = renderHook((props) => {
|
|
7
|
-
const observable = useAsObservable(props.value);
|
|
8
|
-
React.useEffect(() => {
|
|
9
|
-
const subscription = observable.subscribe(v => {
|
|
10
|
-
receivedValues.push(v);
|
|
11
|
-
});
|
|
12
|
-
return () => {
|
|
13
|
-
subscription.unsubscribe();
|
|
14
|
-
};
|
|
15
|
-
}, []);
|
|
16
|
-
}, { initialProps: { value: 'initial' } });
|
|
17
|
-
rerender({ value: 'rerender' });
|
|
18
|
-
rerender({ value: 'rerender again' });
|
|
19
|
-
expect(receivedValues).toEqual(['initial', 'rerender', 'rerender again']);
|
|
20
|
-
unmount();
|
|
21
|
-
});
|
|
22
|
-
test('the returned observable should *not* receive a new value when component is rendered with an unchanged value', () => {
|
|
23
|
-
const receivedValues = [];
|
|
24
|
-
const { unmount, rerender } = renderHook((props) => {
|
|
25
|
-
const observable = useAsObservable(props.value);
|
|
26
|
-
React.useEffect(() => {
|
|
27
|
-
const subscription = observable.subscribe(v => {
|
|
28
|
-
receivedValues.push(v);
|
|
29
|
-
});
|
|
30
|
-
return () => {
|
|
31
|
-
subscription.unsubscribe();
|
|
32
|
-
};
|
|
33
|
-
}, []);
|
|
34
|
-
}, { initialProps: { value: 'some value' } });
|
|
35
|
-
rerender({ value: 'some value' });
|
|
36
|
-
rerender({ value: 'some value' });
|
|
37
|
-
expect(receivedValues).toEqual(['some value']);
|
|
38
|
-
unmount();
|
|
39
|
-
});
|
|
40
|
-
test('the returned observable should have the same identity across multiple re-renders/hook calls', () => {
|
|
41
|
-
const returnValues = [];
|
|
42
|
-
const { unmount, rerender } = renderHook(() => {
|
|
43
|
-
returnValues.push(useAsObservable('render'));
|
|
44
|
-
});
|
|
45
|
-
rerender();
|
|
46
|
-
rerender();
|
|
47
|
-
const [initial, firstRerender, secondRerender] = returnValues;
|
|
48
|
-
expect(initial).toBe(firstRerender);
|
|
49
|
-
expect(firstRerender).toBe(secondRerender);
|
|
50
|
-
unmount();
|
|
51
|
-
});
|
|
52
|
-
test('the returned observable should complete on unmount', () => {
|
|
53
|
-
let didComplete = false;
|
|
54
|
-
const { unmount, rerender } = renderHook(() => {
|
|
55
|
-
const observable = useAsObservable('render');
|
|
56
|
-
React.useEffect(() => {
|
|
57
|
-
const subscription = observable.subscribe({
|
|
58
|
-
complete: () => {
|
|
59
|
-
didComplete = true;
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
return () => {
|
|
63
|
-
subscription.unsubscribe();
|
|
64
|
-
};
|
|
65
|
-
}, []);
|
|
66
|
-
});
|
|
67
|
-
expect(didComplete).toBe(false);
|
|
68
|
-
rerender();
|
|
69
|
-
expect(didComplete).toBe(false);
|
|
70
|
-
unmount();
|
|
71
|
-
expect(didComplete).toBe(true);
|
|
72
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const wrapDisplayName: (BaseComponent: Function, wrapperName: string) => string;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
const getDisplayName = (Component) => {
|
|
2
|
-
if (typeof Component === 'string') {
|
|
3
|
-
return Component;
|
|
4
|
-
}
|
|
5
|
-
return (Component && (Component.displayName || Component.name)) || 'Unknown';
|
|
6
|
-
};
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/ban-types
|
|
8
|
-
export const wrapDisplayName = (BaseComponent, wrapperName) => `${wrapperName}(${getDisplayName(BaseComponent)})`;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
import { FunctionComponent, ReactNode, Ref } from 'react';
|
|
3
|
-
declare type Component<Props> = (input$: Observable<Props>) => Observable<ReactNode>;
|
|
4
|
-
export declare function reactiveComponent<Props>(observable: Observable<Props>): FunctionComponent<Props>;
|
|
5
|
-
export declare function reactiveComponent<Props>(component: Component<Props>): FunctionComponent<Props>;
|
|
6
|
-
declare type ForwardRefComponent<RefType, Props> = (input$: Observable<Props>, ref: Ref<RefType>) => Observable<ReactNode>;
|
|
7
|
-
export declare function forwardRef<RefType, Props = {}>(component: ForwardRefComponent<RefType, Props>): import("react").ForwardRefExoticComponent<import("react").PropsWithoutRef<Props> & import("react").RefAttributes<RefType>>;
|
|
8
|
-
export {};
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { wrapDisplayName } from './displayName';
|
|
2
|
-
import { useAsObservable } from './useAsObservable';
|
|
3
|
-
import { useObservable } from './useObservable';
|
|
4
|
-
import { createElement, Fragment, useRef, forwardRef as reactForwardRef, } from 'react';
|
|
5
|
-
function fromComponent(component) {
|
|
6
|
-
const wrappedComponent = (props) => {
|
|
7
|
-
return createElement(Fragment, null, useObservable(useRef(component(useAsObservable(props))).current));
|
|
8
|
-
};
|
|
9
|
-
wrappedComponent.displayName = wrapDisplayName(component, 'reactiveComponent');
|
|
10
|
-
return wrappedComponent;
|
|
11
|
-
}
|
|
12
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
13
|
-
function fromObservable(input$) {
|
|
14
|
-
return function ReactiveComponent() {
|
|
15
|
-
return createElement(Fragment, null, useObservable(input$));
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
export function reactiveComponent(observableOrComponent) {
|
|
19
|
-
return typeof observableOrComponent === 'function'
|
|
20
|
-
? fromComponent(observableOrComponent)
|
|
21
|
-
: fromObservable(observableOrComponent);
|
|
22
|
-
}
|
|
23
|
-
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/ban-types
|
|
24
|
-
export function forwardRef(component) {
|
|
25
|
-
const wrappedComponent = reactForwardRef((props, ref) => {
|
|
26
|
-
return createElement(Fragment, null, useObservable(useRef(component(useAsObservable(props), ref)).current));
|
|
27
|
-
});
|
|
28
|
-
wrappedComponent.displayName = wrapDisplayName(component, 'reactiveComponent');
|
|
29
|
-
return wrappedComponent;
|
|
30
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
/**
|
|
3
|
-
* React hook to convert any props or state value into an observable
|
|
4
|
-
* Returns an observable representing updates to any React value (props, state or any other calculated value)
|
|
5
|
-
* Note: the returned observable is the same instance throughout the component lifecycle
|
|
6
|
-
* @param value
|
|
7
|
-
* @deprecated use an `of` operator and `useMemoObservable` instead for a faster, more robust and siimpler solution
|
|
8
|
-
*/
|
|
9
|
-
export declare function useAsObservable<T>(value: T): Observable<T>;
|
|
10
|
-
export declare function useAsObservable<T, K>(value: T, operator: (input: Observable<T>) => Observable<K>): Observable<K>;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { BehaviorSubject } from 'rxjs';
|
|
2
|
-
import { useCallback, useEffect, useRef } from 'react';
|
|
3
|
-
import { distinctUntilChanged } from 'rxjs/operators';
|
|
4
|
-
export function useAsObservable(value, operator) {
|
|
5
|
-
const setup = useCallback(() => {
|
|
6
|
-
const subject = new BehaviorSubject(value);
|
|
7
|
-
const observable = subject.asObservable().pipe(distinctUntilChanged());
|
|
8
|
-
return [operator ? observable.pipe(operator) : observable, subject];
|
|
9
|
-
}, []);
|
|
10
|
-
const ref = useRef();
|
|
11
|
-
if (!ref.current) {
|
|
12
|
-
ref.current = setup();
|
|
13
|
-
}
|
|
14
|
-
const [observable] = ref.current;
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
if (!ref.current) {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
const [, subject] = ref.current;
|
|
20
|
-
subject.next(value);
|
|
21
|
-
}, [value, ref]);
|
|
22
|
-
const shouldRestoreSubscriptionRef = useRef(false);
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
if (shouldRestoreSubscriptionRef.current) {
|
|
25
|
-
if (!ref.current) {
|
|
26
|
-
ref.current = setup();
|
|
27
|
-
}
|
|
28
|
-
shouldRestoreSubscriptionRef.current = false;
|
|
29
|
-
}
|
|
30
|
-
return () => {
|
|
31
|
-
if (!ref.current) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
// React StrictMode will call effects as `setup + teardown + setup` thus we can't trust this callback as "react is about to unmount"
|
|
35
|
-
// Tracking this ref lets us set the subscription back up on the next `setup` call if needed, and if it really did unmounted then all is well
|
|
36
|
-
shouldRestoreSubscriptionRef.current = true;
|
|
37
|
-
const [, subject] = ref.current;
|
|
38
|
-
subject.complete();
|
|
39
|
-
ref.current = undefined;
|
|
40
|
-
};
|
|
41
|
-
}, []);
|
|
42
|
-
return observable;
|
|
43
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
/**
|
|
3
|
-
* React hook to convert any props or state value into an observable
|
|
4
|
-
* Returns an observable representing updates to any React value (props, state or any other calculated value)
|
|
5
|
-
* Note: the returned observable is the same instance throughout the component lifecycle
|
|
6
|
-
* @param value
|
|
7
|
-
*/
|
|
8
|
-
export declare function useWithObservable<T>(value: T): T | undefined;
|
|
9
|
-
export declare function useWithObservable<T, K>(value: T, operator: (input: Observable<T>) => Observable<K>): K | undefined;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { useObservable } from './useObservable';
|
|
2
|
-
import { useAsObservable } from './useAsObservable';
|
|
3
|
-
export function useWithObservable(value, operator) {
|
|
4
|
-
return operator
|
|
5
|
-
? useObservable(useAsObservable(value, operator))
|
|
6
|
-
: useObservable(useAsObservable(value));
|
|
7
|
-
}
|
package/dist/es2015/utils.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Observable, OperatorFunction } from 'rxjs';
|
|
2
|
-
import { Dispatch, SetStateAction, Context } from 'react';
|
|
3
|
-
export declare function observeState<T>(initial: T | (() => T)): [Observable<T>, Dispatch<SetStateAction<T>>];
|
|
4
|
-
export declare function observeCallback<T>(): [Observable<T>, (arg: T) => void];
|
|
5
|
-
export declare function observeCallback<T, K>(operator: OperatorFunction<T, K>): [Observable<K>, (arg: T) => void];
|
|
6
|
-
export declare function observeContext<T>(context: Context<T>): Observable<T>;
|
|
7
|
-
export declare function observeElement<T>(): [Observable<T | null>, (el: T | null) => void];
|
package/dist/es2015/utils.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { useAsObservable } from './useAsObservable';
|
|
2
|
-
import { observableCallback } from 'observable-callback';
|
|
3
|
-
import { startWith } from 'rxjs/operators';
|
|
4
|
-
import { useContext, useRef, useState } from 'react';
|
|
5
|
-
const createState = (initialState) => observableCallback(startWith(initialState));
|
|
6
|
-
export function observeState(initial) {
|
|
7
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
8
|
-
const [value, update] = useState(initial);
|
|
9
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
10
|
-
return [useAsObservable(value), update];
|
|
11
|
-
}
|
|
12
|
-
export function observeCallback(operator) {
|
|
13
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
14
|
-
const ref = useRef();
|
|
15
|
-
if (!ref.current) {
|
|
16
|
-
ref.current = operator ? observableCallback(operator) : observableCallback();
|
|
17
|
-
}
|
|
18
|
-
return ref.current;
|
|
19
|
-
}
|
|
20
|
-
export function observeContext(context) {
|
|
21
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
22
|
-
return useAsObservable(useContext(context));
|
|
23
|
-
}
|
|
24
|
-
export function observeElement() {
|
|
25
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
26
|
-
const ref = useRef();
|
|
27
|
-
if (!ref.current) {
|
|
28
|
-
ref.current = createState(null);
|
|
29
|
-
}
|
|
30
|
-
return ref.current;
|
|
31
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Observable } from 'rxjs';
|
|
3
|
-
declare type ObservableFactory<SourceProps, TargetProps> = (props$: Observable<SourceProps>) => Observable<TargetProps>;
|
|
4
|
-
/**
|
|
5
|
-
* @deprecated Use reactiveComponent instead
|
|
6
|
-
*/
|
|
7
|
-
export declare function withPropsStream<SourceProps, TargetProps>(observableOrFactory: Observable<TargetProps> | ObservableFactory<SourceProps, TargetProps>, TargetComponent: React.ComponentType<TargetProps>): React.FunctionComponent<SourceProps>;
|
|
8
|
-
export {};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { map } from 'rxjs/operators';
|
|
3
|
-
import { wrapDisplayName } from './displayName';
|
|
4
|
-
import { reactiveComponent } from './reactiveComponent';
|
|
5
|
-
/**
|
|
6
|
-
* @deprecated Use reactiveComponent instead
|
|
7
|
-
*/
|
|
8
|
-
export function withPropsStream(observableOrFactory, TargetComponent) {
|
|
9
|
-
const ComposedComponent = reactiveComponent(sourceProps$ => {
|
|
10
|
-
const targetProps$ = typeof observableOrFactory === 'function'
|
|
11
|
-
? observableOrFactory(sourceProps$)
|
|
12
|
-
: observableOrFactory;
|
|
13
|
-
return targetProps$.pipe(map(props => React.createElement(TargetComponent, Object.assign({}, props))));
|
|
14
|
-
});
|
|
15
|
-
ComposedComponent.displayName = wrapDisplayName(TargetComponent, 'withPropsStream');
|
|
16
|
-
return ComposedComponent;
|
|
17
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
import { ComponentType, ReactNode } from 'react';
|
|
3
|
-
interface Props<T> {
|
|
4
|
-
observable: Observable<T>;
|
|
5
|
-
children: (value: T) => ReactNode;
|
|
6
|
-
}
|
|
7
|
-
declare type ObservableComponent<T> = ComponentType<Props<T>>;
|
|
8
|
-
/**
|
|
9
|
-
* @deprecated Use the useObservable hook instead
|
|
10
|
-
*/
|
|
11
|
-
export declare const WithObservable: ObservableComponent<unknown>;
|
|
12
|
-
export {};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { distinctUntilChanged, map, switchMap } from 'rxjs/operators';
|
|
2
|
-
import { reactiveComponent } from './reactiveComponent';
|
|
3
|
-
function createWithObservable() {
|
|
4
|
-
return reactiveComponent(function (props$) {
|
|
5
|
-
return props$.pipe(distinctUntilChanged(function (props, prevProps) { return props.observable === prevProps.observable; }), switchMap(function (props) {
|
|
6
|
-
return props.observable.pipe(map(function (observableValue) { return props.children(observableValue); }));
|
|
7
|
-
}));
|
|
8
|
-
});
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* @deprecated Use the useObservable hook instead
|
|
12
|
-
*/
|
|
13
|
-
export var WithObservable = createWithObservable();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { useAsObservable } from '../useAsObservable';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import { renderHook } from '@testing-library/react';
|
|
4
|
-
test('the returned observable should receive a new value when component is rendered with a new value', function () {
|
|
5
|
-
var receivedValues = [];
|
|
6
|
-
var _a = renderHook(function (props) {
|
|
7
|
-
var observable = useAsObservable(props.value);
|
|
8
|
-
React.useEffect(function () {
|
|
9
|
-
var subscription = observable.subscribe(function (v) {
|
|
10
|
-
receivedValues.push(v);
|
|
11
|
-
});
|
|
12
|
-
return function () {
|
|
13
|
-
subscription.unsubscribe();
|
|
14
|
-
};
|
|
15
|
-
}, []);
|
|
16
|
-
}, { initialProps: { value: 'initial' } }), unmount = _a.unmount, rerender = _a.rerender;
|
|
17
|
-
rerender({ value: 'rerender' });
|
|
18
|
-
rerender({ value: 'rerender again' });
|
|
19
|
-
expect(receivedValues).toEqual(['initial', 'rerender', 'rerender again']);
|
|
20
|
-
unmount();
|
|
21
|
-
});
|
|
22
|
-
test('the returned observable should *not* receive a new value when component is rendered with an unchanged value', function () {
|
|
23
|
-
var receivedValues = [];
|
|
24
|
-
var _a = renderHook(function (props) {
|
|
25
|
-
var observable = useAsObservable(props.value);
|
|
26
|
-
React.useEffect(function () {
|
|
27
|
-
var subscription = observable.subscribe(function (v) {
|
|
28
|
-
receivedValues.push(v);
|
|
29
|
-
});
|
|
30
|
-
return function () {
|
|
31
|
-
subscription.unsubscribe();
|
|
32
|
-
};
|
|
33
|
-
}, []);
|
|
34
|
-
}, { initialProps: { value: 'some value' } }), unmount = _a.unmount, rerender = _a.rerender;
|
|
35
|
-
rerender({ value: 'some value' });
|
|
36
|
-
rerender({ value: 'some value' });
|
|
37
|
-
expect(receivedValues).toEqual(['some value']);
|
|
38
|
-
unmount();
|
|
39
|
-
});
|
|
40
|
-
test('the returned observable should have the same identity across multiple re-renders/hook calls', function () {
|
|
41
|
-
var returnValues = [];
|
|
42
|
-
var _a = renderHook(function () {
|
|
43
|
-
returnValues.push(useAsObservable('render'));
|
|
44
|
-
}), unmount = _a.unmount, rerender = _a.rerender;
|
|
45
|
-
rerender();
|
|
46
|
-
rerender();
|
|
47
|
-
var initial = returnValues[0], firstRerender = returnValues[1], secondRerender = returnValues[2];
|
|
48
|
-
expect(initial).toBe(firstRerender);
|
|
49
|
-
expect(firstRerender).toBe(secondRerender);
|
|
50
|
-
unmount();
|
|
51
|
-
});
|
|
52
|
-
test('the returned observable should complete on unmount', function () {
|
|
53
|
-
var didComplete = false;
|
|
54
|
-
var _a = renderHook(function () {
|
|
55
|
-
var observable = useAsObservable('render');
|
|
56
|
-
React.useEffect(function () {
|
|
57
|
-
var subscription = observable.subscribe({
|
|
58
|
-
complete: function () {
|
|
59
|
-
didComplete = true;
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
return function () {
|
|
63
|
-
subscription.unsubscribe();
|
|
64
|
-
};
|
|
65
|
-
}, []);
|
|
66
|
-
}), unmount = _a.unmount, rerender = _a.rerender;
|
|
67
|
-
expect(didComplete).toBe(false);
|
|
68
|
-
rerender();
|
|
69
|
-
expect(didComplete).toBe(false);
|
|
70
|
-
unmount();
|
|
71
|
-
expect(didComplete).toBe(true);
|
|
72
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const wrapDisplayName: (BaseComponent: Function, wrapperName: string) => string;
|
package/dist/esm/displayName.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
var getDisplayName = function (Component) {
|
|
2
|
-
if (typeof Component === 'string') {
|
|
3
|
-
return Component;
|
|
4
|
-
}
|
|
5
|
-
return (Component && (Component.displayName || Component.name)) || 'Unknown';
|
|
6
|
-
};
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/ban-types
|
|
8
|
-
export var wrapDisplayName = function (BaseComponent, wrapperName) {
|
|
9
|
-
return "".concat(wrapperName, "(").concat(getDisplayName(BaseComponent), ")");
|
|
10
|
-
};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
import { FunctionComponent, ReactNode, Ref } from 'react';
|
|
3
|
-
declare type Component<Props> = (input$: Observable<Props>) => Observable<ReactNode>;
|
|
4
|
-
export declare function reactiveComponent<Props>(observable: Observable<Props>): FunctionComponent<Props>;
|
|
5
|
-
export declare function reactiveComponent<Props>(component: Component<Props>): FunctionComponent<Props>;
|
|
6
|
-
declare type ForwardRefComponent<RefType, Props> = (input$: Observable<Props>, ref: Ref<RefType>) => Observable<ReactNode>;
|
|
7
|
-
export declare function forwardRef<RefType, Props = {}>(component: ForwardRefComponent<RefType, Props>): import("react").ForwardRefExoticComponent<import("react").PropsWithoutRef<Props> & import("react").RefAttributes<RefType>>;
|
|
8
|
-
export {};
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { wrapDisplayName } from './displayName';
|
|
2
|
-
import { useAsObservable } from './useAsObservable';
|
|
3
|
-
import { useObservable } from './useObservable';
|
|
4
|
-
import { createElement, Fragment, useRef, forwardRef as reactForwardRef, } from 'react';
|
|
5
|
-
function fromComponent(component) {
|
|
6
|
-
var wrappedComponent = function (props) {
|
|
7
|
-
return createElement(Fragment, null, useObservable(useRef(component(useAsObservable(props))).current));
|
|
8
|
-
};
|
|
9
|
-
wrappedComponent.displayName = wrapDisplayName(component, 'reactiveComponent');
|
|
10
|
-
return wrappedComponent;
|
|
11
|
-
}
|
|
12
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
13
|
-
function fromObservable(input$) {
|
|
14
|
-
return function ReactiveComponent() {
|
|
15
|
-
return createElement(Fragment, null, useObservable(input$));
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
export function reactiveComponent(observableOrComponent) {
|
|
19
|
-
return typeof observableOrComponent === 'function'
|
|
20
|
-
? fromComponent(observableOrComponent)
|
|
21
|
-
: fromObservable(observableOrComponent);
|
|
22
|
-
}
|
|
23
|
-
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/ban-types
|
|
24
|
-
export function forwardRef(component) {
|
|
25
|
-
var wrappedComponent = reactForwardRef(function (props, ref) {
|
|
26
|
-
return createElement(Fragment, null, useObservable(useRef(component(useAsObservable(props), ref)).current));
|
|
27
|
-
});
|
|
28
|
-
wrappedComponent.displayName = wrapDisplayName(component, 'reactiveComponent');
|
|
29
|
-
return wrappedComponent;
|
|
30
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
/**
|
|
3
|
-
* React hook to convert any props or state value into an observable
|
|
4
|
-
* Returns an observable representing updates to any React value (props, state or any other calculated value)
|
|
5
|
-
* Note: the returned observable is the same instance throughout the component lifecycle
|
|
6
|
-
* @param value
|
|
7
|
-
* @deprecated use an `of` operator and `useMemoObservable` instead for a faster, more robust and siimpler solution
|
|
8
|
-
*/
|
|
9
|
-
export declare function useAsObservable<T>(value: T): Observable<T>;
|
|
10
|
-
export declare function useAsObservable<T, K>(value: T, operator: (input: Observable<T>) => Observable<K>): Observable<K>;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { BehaviorSubject } from 'rxjs';
|
|
2
|
-
import { useCallback, useEffect, useRef } from 'react';
|
|
3
|
-
import { distinctUntilChanged } from 'rxjs/operators';
|
|
4
|
-
export function useAsObservable(value, operator) {
|
|
5
|
-
var setup = useCallback(function () {
|
|
6
|
-
var subject = new BehaviorSubject(value);
|
|
7
|
-
var observable = subject.asObservable().pipe(distinctUntilChanged());
|
|
8
|
-
return [operator ? observable.pipe(operator) : observable, subject];
|
|
9
|
-
}, []);
|
|
10
|
-
var ref = useRef();
|
|
11
|
-
if (!ref.current) {
|
|
12
|
-
ref.current = setup();
|
|
13
|
-
}
|
|
14
|
-
var observable = ref.current[0];
|
|
15
|
-
useEffect(function () {
|
|
16
|
-
if (!ref.current) {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
var _a = ref.current, subject = _a[1];
|
|
20
|
-
subject.next(value);
|
|
21
|
-
}, [value, ref]);
|
|
22
|
-
var shouldRestoreSubscriptionRef = useRef(false);
|
|
23
|
-
useEffect(function () {
|
|
24
|
-
if (shouldRestoreSubscriptionRef.current) {
|
|
25
|
-
if (!ref.current) {
|
|
26
|
-
ref.current = setup();
|
|
27
|
-
}
|
|
28
|
-
shouldRestoreSubscriptionRef.current = false;
|
|
29
|
-
}
|
|
30
|
-
return function () {
|
|
31
|
-
if (!ref.current) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
// React StrictMode will call effects as `setup + teardown + setup` thus we can't trust this callback as "react is about to unmount"
|
|
35
|
-
// Tracking this ref lets us set the subscription back up on the next `setup` call if needed, and if it really did unmounted then all is well
|
|
36
|
-
shouldRestoreSubscriptionRef.current = true;
|
|
37
|
-
var _a = ref.current, subject = _a[1];
|
|
38
|
-
subject.complete();
|
|
39
|
-
ref.current = undefined;
|
|
40
|
-
};
|
|
41
|
-
}, []);
|
|
42
|
-
return observable;
|
|
43
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
/**
|
|
3
|
-
* React hook to convert any props or state value into an observable
|
|
4
|
-
* Returns an observable representing updates to any React value (props, state or any other calculated value)
|
|
5
|
-
* Note: the returned observable is the same instance throughout the component lifecycle
|
|
6
|
-
* @param value
|
|
7
|
-
*/
|
|
8
|
-
export declare function useWithObservable<T>(value: T): T | undefined;
|
|
9
|
-
export declare function useWithObservable<T, K>(value: T, operator: (input: Observable<T>) => Observable<K>): K | undefined;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { useObservable } from './useObservable';
|
|
2
|
-
import { useAsObservable } from './useAsObservable';
|
|
3
|
-
export function useWithObservable(value, operator) {
|
|
4
|
-
return operator
|
|
5
|
-
? useObservable(useAsObservable(value, operator))
|
|
6
|
-
: useObservable(useAsObservable(value));
|
|
7
|
-
}
|
package/dist/esm/utils.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Observable, OperatorFunction } from 'rxjs';
|
|
2
|
-
import { Dispatch, SetStateAction, Context } from 'react';
|
|
3
|
-
export declare function observeState<T>(initial: T | (() => T)): [Observable<T>, Dispatch<SetStateAction<T>>];
|
|
4
|
-
export declare function observeCallback<T>(): [Observable<T>, (arg: T) => void];
|
|
5
|
-
export declare function observeCallback<T, K>(operator: OperatorFunction<T, K>): [Observable<K>, (arg: T) => void];
|
|
6
|
-
export declare function observeContext<T>(context: Context<T>): Observable<T>;
|
|
7
|
-
export declare function observeElement<T>(): [Observable<T | null>, (el: T | null) => void];
|
package/dist/esm/utils.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { useAsObservable } from './useAsObservable';
|
|
2
|
-
import { observableCallback } from 'observable-callback';
|
|
3
|
-
import { startWith } from 'rxjs/operators';
|
|
4
|
-
import { useContext, useRef, useState } from 'react';
|
|
5
|
-
var createState = function (initialState) { return observableCallback(startWith(initialState)); };
|
|
6
|
-
export function observeState(initial) {
|
|
7
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
8
|
-
var _a = useState(initial), value = _a[0], update = _a[1];
|
|
9
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
10
|
-
return [useAsObservable(value), update];
|
|
11
|
-
}
|
|
12
|
-
export function observeCallback(operator) {
|
|
13
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
14
|
-
var ref = useRef();
|
|
15
|
-
if (!ref.current) {
|
|
16
|
-
ref.current = operator ? observableCallback(operator) : observableCallback();
|
|
17
|
-
}
|
|
18
|
-
return ref.current;
|
|
19
|
-
}
|
|
20
|
-
export function observeContext(context) {
|
|
21
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
22
|
-
return useAsObservable(useContext(context));
|
|
23
|
-
}
|
|
24
|
-
export function observeElement() {
|
|
25
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
26
|
-
var ref = useRef();
|
|
27
|
-
if (!ref.current) {
|
|
28
|
-
ref.current = createState(null);
|
|
29
|
-
}
|
|
30
|
-
return ref.current;
|
|
31
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Observable } from 'rxjs';
|
|
3
|
-
declare type ObservableFactory<SourceProps, TargetProps> = (props$: Observable<SourceProps>) => Observable<TargetProps>;
|
|
4
|
-
/**
|
|
5
|
-
* @deprecated Use reactiveComponent instead
|
|
6
|
-
*/
|
|
7
|
-
export declare function withPropsStream<SourceProps, TargetProps>(observableOrFactory: Observable<TargetProps> | ObservableFactory<SourceProps, TargetProps>, TargetComponent: React.ComponentType<TargetProps>): React.FunctionComponent<SourceProps>;
|
|
8
|
-
export {};
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
var __assign = (this && this.__assign) || function () {
|
|
2
|
-
__assign = Object.assign || function(t) {
|
|
3
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
-
s = arguments[i];
|
|
5
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
-
t[p] = s[p];
|
|
7
|
-
}
|
|
8
|
-
return t;
|
|
9
|
-
};
|
|
10
|
-
return __assign.apply(this, arguments);
|
|
11
|
-
};
|
|
12
|
-
import * as React from 'react';
|
|
13
|
-
import { map } from 'rxjs/operators';
|
|
14
|
-
import { wrapDisplayName } from './displayName';
|
|
15
|
-
import { reactiveComponent } from './reactiveComponent';
|
|
16
|
-
/**
|
|
17
|
-
* @deprecated Use reactiveComponent instead
|
|
18
|
-
*/
|
|
19
|
-
export function withPropsStream(observableOrFactory, TargetComponent) {
|
|
20
|
-
var ComposedComponent = reactiveComponent(function (sourceProps$) {
|
|
21
|
-
var targetProps$ = typeof observableOrFactory === 'function'
|
|
22
|
-
? observableOrFactory(sourceProps$)
|
|
23
|
-
: observableOrFactory;
|
|
24
|
-
return targetProps$.pipe(map(function (props) { return React.createElement(TargetComponent, __assign({}, props)); }));
|
|
25
|
-
});
|
|
26
|
-
ComposedComponent.displayName = wrapDisplayName(TargetComponent, 'withPropsStream');
|
|
27
|
-
return ComposedComponent;
|
|
28
|
-
}
|
package/src/WithObservable.tsx
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import {Observable} from 'rxjs'
|
|
3
|
-
import {distinctUntilChanged, map, switchMap} from 'rxjs/operators'
|
|
4
|
-
import {reactiveComponent} from './reactiveComponent'
|
|
5
|
-
import {ComponentType, ReactNode} from 'react'
|
|
6
|
-
|
|
7
|
-
interface Props<T> {
|
|
8
|
-
observable: Observable<T>
|
|
9
|
-
children: (value: T) => ReactNode
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
type ObservableComponent<T> = ComponentType<Props<T>>
|
|
13
|
-
|
|
14
|
-
function createWithObservable<T>(): ObservableComponent<T> {
|
|
15
|
-
return reactiveComponent((props$: Observable<Props<T>>) =>
|
|
16
|
-
props$.pipe(
|
|
17
|
-
distinctUntilChanged((props, prevProps) => props.observable === prevProps.observable),
|
|
18
|
-
switchMap(
|
|
19
|
-
(props): Observable<ReactNode> =>
|
|
20
|
-
props.observable.pipe(map((observableValue: T) => props.children(observableValue))),
|
|
21
|
-
),
|
|
22
|
-
),
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @deprecated Use the useObservable hook instead
|
|
28
|
-
*/
|
|
29
|
-
export const WithObservable = createWithObservable()
|