Getting Started
Installation
npm i react-rx rxjsObservable Hooks
useObservable()
Use observables in React components with the useObservable hook.
If you need to subscribe to an observable in your component, this hook will give you the current value from it
Example:
import {useMemo} from 'react'
import {useObservable} from 'react-rx'
import {interval} from 'rxjs'
function MyComponent(props) {
const observable = useMemo(() => interval(100), [])
const number = useObservable(observable, 0)
return <>The number is {number}</>
}The initialValue argument is optional. If its omitted, the value returned from useObservable may be null initially. If the observable emits a value synchronously at subscription time, that value will be used as the initial value, and any initialValue passed as argument to useObservable will be ignored:
import {useMemo} from 'react'
import {useObservable} from 'react-rx'
import {of} from 'rxjs'
// This component will never render "Hello mars!" since the observable emits "world" synchronously.
function MyComponent(props) {
const observable = useMemo(() => of('world'), [])
const planet = useObservable(observable, 'mars')
return <>Hello {planet}!</>
}The disabled option pauses the hook’s active subscription — think of it like pause: true. While disabled is true, the hook will not keep a live subscription that pushes updates into the component, and it returns the last value it already received (or the initialValue if nothing has been received yet). Turning disabled back to false resumes the live subscription.
Important: disabled does not skip the hook’s initial warm-up subscription. useObservable always briefly subscribes during render so a synchronous emission can become the current snapshot. That means cold observables with subscribe-time side effects (for example fromFetch) still run that work even when disabled is true.
import {useEffect, useState} from 'react'
import {useObservable} from 'react-rx'
import {Subject} from 'rxjs'
// While `disabled` is true, later async emissions are ignored and the last
// received value (here the initialValue "mars") is returned.
function MyComponent(props) {
const [observable] = useState(() => new Subject<string>())
const planet = useObservable(observable, 'mars', {disabled: true})
useEffect(() => {
observable.next('world')
}, [observable])
return <>Hello {planet}!</>
}If the goal is to avoid any subscription to a particular observable, do not use disabled. Pass a different observable instead — for example swap in of(null) until you are ready to fetch:
import {useMemo} from 'react'
import {useObservable} from 'react-rx'
import {of} from 'rxjs'
import {fromFetch} from 'rxjs/fetch'
function Users({shouldFetch}: {shouldFetch: boolean}) {
// Prefer swapping the observable over `{disabled: !shouldFetch}`:
// `disabled` still performs the render-phase warm-up subscribe, which would
// fire the request even when `shouldFetch` is false.
const users$ = useMemo(
() =>
shouldFetch
? fromFetch('https://api.github.com/users?per_page=5', {
selector: (response) => response.json(),
})
: of(null),
[shouldFetch],
)
const users = useObservable(users$, null)
return <pre>{JSON.stringify(users, null, 2)}</pre>
}Because the fetch observable is only created (and therefore only ever subscribed) when shouldFetch is true, this guarantees zero subscriptions to fromFetch until then.
useObservableEvent()
This creates an event handler that can be used to create an observable from events.
Here’s an example of a component that displays the current value from a range input:
import {useState} from 'react'
import {useObservableEvent} from 'react-rx'
import {filter, map, tap} from 'rxjs/operators'
const ShowSliderValue = () => {
const [value, setValue] = useState(1)
const handleChange = useObservableEvent((value$) =>
value$.pipe(
// Ignore nullish values
filter(nonNullable),
// Cast to number
map((value) => Number(value)),
// Update local state
tap(setValue),
),
)
return (
<>
<input
type="range"
value={value}
onChange={(event) => handleChange(event.target.value)}
min={1}
max={10}
/>
<div>Value is: {value}</div>
</>
)
}
function nonNullable<T>(v: T): v is NonNullable<T> {
return v != null
}