Created
September 17, 2021 01:47
-
-
Save Peeja/6caf790eb3d68e4025cffc6b3162b913 to your computer and use it in GitHub Desktop.
Read the latest value of an Observable in a React hook (WIP, stashed from another project when it became unnecessary.)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @jest-environment jsdom | |
*/ | |
import { useObservable } from "./useObservable"; | |
import { renderHook, act } from "@testing-library/react-hooks"; | |
import { Subject } from "rxjs"; | |
describe("useObservable()", () => { | |
it("returns each value emitted by the Observable", () => { | |
const subject = new Subject<number>(); | |
const { result } = renderHook(() => useObservable(subject)); | |
expect(result.current).toBeUndefined(); | |
act(() => { | |
subject.next(1); | |
}); | |
expect(result.current).toBe(1); | |
act(() => { | |
subject.next(2); | |
}); | |
expect(result.current).toBe(2); | |
}); | |
it("throws errors emitted by the Observable", () => { | |
const subject = new Subject<number>(); | |
const { result } = renderHook(() => useObservable(subject)); | |
expect(result.current).toBeUndefined(); | |
// BOOKMARK: Why can't I catch this thing? | |
act(() => { | |
try { | |
subject.error(new Error("Something went wrong!")); | |
1; //? | |
} catch (e) { | |
console.log(e); | |
} | |
}); | |
expect(result.current).toBe(1); | |
act(() => { | |
subject.next(2); | |
}); | |
expect(result.current).toBe(2); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useState } from "react"; | |
import { Observable } from "rxjs"; | |
/** | |
* Subscribes to an {@link Observable}. First returns `undefined`, then returns | |
* each value emitted by the Observable. | |
* | |
* Note: Currently, Observable errors and completions are ignored. | |
* @param observable The Observable to watch | |
* @returns undefined, then each value emitted by the Observable. | |
*/ | |
export const useObservable = <T>(observable: Observable<T>): T | undefined => { | |
const [value, setValue] = useState<T>(); | |
// const [error, setError] = useState<unknown>(); | |
// if (error) throw error; | |
useEffect(() => { | |
const subscription = observable.subscribe(setValue); | |
return () => subscription.unsubscribe(); | |
}, [observable, setValue]); | |
return value; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment