React hooks for working with RxJS observables.
npm install use-observable-hooks
Full API documentation is available at useobservablehooks.com.
Subscribe to an RxJS Observable and receive the current value and any error.
import { useObservable } from 'use-observable-hooks';
import { interval } from 'rxjs';
function Timer() {
const [count, error] = useObservable(interval(1000));
return <div>Count: {count ?? 'Loading...'}</div>;
}
With RxJS operators:
import { useObservable } from 'use-observable-hooks';
import { interval } from 'rxjs';
import { map, filter } from 'rxjs/operators';
function EvenNumbers() {
const [evenCount] = useObservable(
interval(1000),
filter((n) => n % 2 === 0),
map((n) => n * 10)
);
return <div>Even count x10: {evenCount ?? 'Waiting...'}</div>;
}
Use an RxJS BehaviorSubject with state management capabilities. A BehaviorSubject always has a current value.
import { useBehaviorSubject } from 'use-observable-hooks';
function Counter() {
const [count, setCount, error] = useBehaviorSubject(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
With RxJS operators:
import { useBehaviorSubject } from 'use-observable-hooks';
import { map } from 'rxjs/operators';
function DoubleCounter() {
const [doubledCount, setCount] = useBehaviorSubject(
0,
map((n) => n * 2)
);
return (
<button onClick={() => setCount(doubledCount / 2 + 1)}>
Doubled Count: {doubledCount}
</button>
);
}
Use an RxJS Subject to emit and receive values. Unlike BehaviorSubject, a Subject has no initial value.
import { useSubject } from 'use-observable-hooks';
function EventEmitter() {
const [event, emitEvent, error] = useSubject<string>();
return (
<div>
<p>Last Event: {event ?? 'None'}</p>
<button onClick={() => emitEvent('Click')}>Emit Click</button>
<button onClick={() => emitEvent('Hover')}>Emit Hover</button>
</div>
);
}
With RxJS operators:
import { useSubject } from 'use-observable-hooks';
import { debounceTime, map } from 'rxjs/operators';
function SearchInput() {
const [debouncedSearch, setSearch] = useSubject<string>(
debounceTime(300),
map((query) => query.toLowerCase())
);
return (
<div>
<input onChange={(e) => setSearch(e.target.value)} />
<p>Searching for: {debouncedSearch ?? 'Nothing yet'}</p>
</div>
);
}