From 70697d962604130fb0f0b012e1d55bb45017130c Mon Sep 17 00:00:00 2001 From: streamich Date: Thu, 30 May 2019 19:57:10 +0200 Subject: [PATCH 1/3] =?UTF-8?q?style:=20=F0=9F=92=84=20fix=20linting=20err?= =?UTF-8?q?or?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/useSetState.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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)); From d0c3713decc27c5587ad1d60809288d019ea608d Mon Sep 17 00:00:00 2001 From: streamich Date: Thu, 30 May 2019 20:39:07 +0200 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20improve=20useObserva?= =?UTF-8?q?ble()=20type=20annotations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/useObservable.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) 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; From 3a0c683099bb224fddd2d7226e81a51589a6e621 Mon Sep 17 00:00:00 2001 From: streamich Date: Thu, 30 May 2019 20:43:53 +0200 Subject: [PATCH 3/3] =?UTF-8?q?test:=20=F0=9F=92=8D=20add=20tests=20for=20?= =?UTF-8?q?useObservable()=20hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- babel.config.js | 1 + package.json | 1 + src/__tests__/useObservable.test.tsx | 35 ++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 src/__tests__/useObservable.test.tsx 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', () => {});