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