diff --git a/babel.config.js b/babel.config.js index 4bea0c59..b8339150 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,3 +1,4 @@ module.exports = { presets: ['@babel/preset-env', '@babel/preset-react', "@babel/preset-typescript"], + plugins: ['@babel/plugin-syntax-dynamic-import'] }; \ No newline at end of file diff --git a/package.json b/package.json index 0a4294b8..c476782b 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ }, "homepage": "https://github.com/streamich/react-use#readme", "dependencies": { + "@babel/plugin-syntax-dynamic-import": "^7.2.0", "copy-to-clipboard": "^3.1.0", "nano-css": "^5.1.0", "react-fast-compare": "^2.0.4", diff --git a/src/__tests__/useObservable.test.tsx b/src/__tests__/useObservable.test.tsx new file mode 100644 index 00000000..6bba8c87 --- /dev/null +++ b/src/__tests__/useObservable.test.tsx @@ -0,0 +1,35 @@ +import { act, renderHook } from 'react-hooks-testing-library'; +import { Subject } from 'rxjs'; +import { useObservable } from '..'; + +test('default initial value is undefined', () => { + const subject$ = new Subject(); + const { result } = renderHook(() => useObservable(subject$)); + + expect(result.current).toBe(undefined); +}); + +test('can specify initial value', () => { + const subject$ = new Subject(); + const { result } = renderHook(() => useObservable(subject$, 123)); + + expect(result.current).toBe(123); +}); + +test('returns the latest value of observables', () => { + const subject$ = new Subject(); + const { result } = renderHook(() => useObservable(subject$, 123)); + + act(() => { + subject$.next(125); + }); + expect(result.current).toBe(125); + + act(() => { + subject$.next(300); + subject$.next(400); + }); + expect(result.current).toBe(400); +}); + +xtest('subscribes to observable only once', () => {}); diff --git a/src/useObservable.ts b/src/useObservable.ts index 14a48286..49832492 100644 --- a/src/useObservable.ts +++ b/src/useObservable.ts @@ -1,6 +1,16 @@ import { useEffect, useState } from 'react'; -const useObservable = (observable$, initialValue?: T): T | undefined => { +export interface Observable { + subscribe: ( + listener: (value: T) => void + ) => { + unsubscribe: () => void; + }; +} + +function useObservable(observable$: Observable): T | undefined; +function useObservable(observable$: Observable, initialValue: T): T; +function useObservable(observable$: Observable, initialValue?: T): T | undefined { const [value, update] = useState(initialValue); useEffect(() => { @@ -9,6 +19,6 @@ const useObservable = (observable$, initialValue?: T): T | undefined => { }, [observable$]); return value; -}; +} export default useObservable; diff --git a/src/useSetState.ts b/src/useSetState.ts index 056eaca6..d0900439 100644 --- a/src/useSetState.ts +++ b/src/useSetState.ts @@ -1,6 +1,8 @@ import { useState } from 'react'; -const useSetState = (initialState: T = {} as T): [T, (patch: Partial | ((prevState: T) => Partial)) => void] => { +const useSetState = ( + initialState: T = {} as T +): [T, (patch: Partial | ((prevState: T) => Partial)) => void] => { const [state, set] = useState(initialState); const setState = patch => { set(prevState => Object.assign({}, prevState, patch instanceof Function ? patch(prevState) : patch));