diff --git a/src/useAsObservable.ts b/src/useAsObservable.ts index 5889e478..d598a195 100644 --- a/src/useAsObservable.ts +++ b/src/useAsObservable.ts @@ -1,6 +1,5 @@ import {BehaviorSubject, Observable} from 'rxjs' -import {useCallback, useRef} from 'react' -import {useIsomorphicEffect} from './useIsomorphicEffect' +import {useCallback, useEffect, useRef} from 'react' import {distinctUntilChanged} from 'rxjs/operators' /** @@ -33,7 +32,7 @@ export function useAsObservable( const [observable] = ref.current - useIsomorphicEffect(() => { + useEffect(() => { if (!ref.current) { return } @@ -41,11 +40,22 @@ export function useAsObservable( subject.next(value) }, [value, ref]) - useIsomorphicEffect(() => { + const shouldRestoreSubscriptionRef = useRef(false) + useEffect(() => { + if (shouldRestoreSubscriptionRef.current) { + if (!ref.current) { + ref.current = setup() + } + shouldRestoreSubscriptionRef.current = false + } + return () => { if (!ref.current) { return } + // React StrictMode will call effects as `setup + teardown + setup` thus we can't trust this callback as "react is about to unmount" + // 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 + shouldRestoreSubscriptionRef.current = true const [, subject] = ref.current subject.complete() ref.current = undefined diff --git a/src/useObservable.ts b/src/useObservable.ts index f88563cd..4d32d52c 100644 --- a/src/useObservable.ts +++ b/src/useObservable.ts @@ -38,6 +38,9 @@ export function useObservable(observable: Observable, initialValue?: T | ( [() => T, Parameters[0]] >(() => { const store = getOrCreateStore(observable, getValue(initialValue)) + if (store.subscription.closed) { + store.subscription = store.observable.subscribe() + } return [ function getSnapshot() { // @TODO: perf opt opportunity: we could do `store.subscription.unsubscribe()` here to clear up some memory, as this subscription is only needed to provide a sync initialValue.