Skip to content

Instantly share code, notes, and snippets.

@buhichan
Created October 13, 2020 07:40
Show Gist options
  • Save buhichan/d147fcd34abb2b37240d71fa8b867264 to your computer and use it in GitHub Desktop.
Save buhichan/d147fcd34abb2b37240d71fa8b867264 to your computer and use it in GitHub Desktop.
use-observables.ts
import { BehaviorSubject, Observable, Subscription, SubscribableOrPromise, from } from "rxjs"
import { skip } from "rxjs/operators"
import * as React from "react"
import { useSubscription } from "use-subscription"
type ObservedValueOf<T> = T extends BehaviorSubject<infer U1> ? U1 : T extends Observable<infer U2> ? U2 | null : never
export function useObservables<T>(ob: T | undefined | null): [ObservedValueOf<T>]
export function useObservables<T1, T2>(ob1: T1 | undefined | null, ob2: T2 | undefined | null): [ObservedValueOf<T1>, ObservedValueOf<T2>]
export function useObservables<T1, T2, T3>(
ob1: T1 | undefined | null,
ob2: T2 | undefined | null,
ob3: T3 | undefined | null
): [ObservedValueOf<T1>, ObservedValueOf<T2>, ObservedValueOf<T3>]
export function useObservables<T1, T2, T3, T4>(
ob1: T1 | undefined | null,
ob2: T2 | undefined | null,
ob3: T3 | undefined | null,
ob4: T4 | undefined | null
): [ObservedValueOf<T1>, ObservedValueOf<T2>, ObservedValueOf<T3>, ObservedValueOf<T4>]
export function useObservables<T1, T2, T3, T4, T5>(
ob1: T1 | undefined | null,
ob2: T2 | undefined | null,
ob3: T3 | undefined | null,
ob4: T4 | undefined | null,
ob5: T5 | undefined | null
): [ObservedValueOf<T1>, ObservedValueOf<T2>, ObservedValueOf<T3>, ObservedValueOf<T4>, ObservedValueOf<T5>]
export function useObservables(...obs: (Observable<any> | null | undefined)[]) {
const currentValue = React.useMemo(
() => ({
value: obs.map(x => (x instanceof BehaviorSubject ? x.value : null)),
}),
obs
)
return useSubscription(
React.useMemo(
() => ({
getCurrentValue: () => currentValue.value,
subscribe: callback => {
let subs = new Subscription()
obs.forEach((x, i) => {
if (x) {
subs.add(
(x instanceof BehaviorSubject ? skip(1)(x) : x).subscribe(v => {
currentValue.value[i] = v
currentValue.value = currentValue.value.slice()
callback()
})
)
}
})
return () => {
subs.unsubscribe()
}
},
}),
obs
)
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment