@anion155/react-rxjs-hooks v0.2.3
React Reactive Hooks and utilities library
This library contains utilities and react hooks related to work with rxjs.
API hooks
import {} from '@anion155/react-rxjs-hooks';useRxSubscription
function useRxSubscription(
fabric: () => Subscription | ObservableInput<unknown>,
deps: DependencyList
): voidCreate and manage subscription to source observable.
const time = 1000;
useRxSubscription(() => interval(time).pipe(
tap(() => console.log('effect like behavior'))
), [time]);Or with observer:
const store = new BehaviorSubject(undefined);
useRxSubscription(() => interval(1000), [], () => store, [store]);
// source.next -> undefined, 0, 1, 2, 3, ...useRxStore
function useRxStore<T>(initial: ReactRxStoreInput<T>): ReactRxStore<T>;Create and controls instance of ReactRxStore with lifecycle, unless store was passed as initial parameter.
const store = useRxStore('value');Note
'Create and controls instance of
ReactRxStorewith lifecycle' means that on unmount instance ofReactRxStorewould be completed.
useRxStoreValue
function useRxStoreValue<T>(store: ReactRxStore<T>): T;Subscribe to store and return it's value.
const store = useRxStore('value');
const value = useRxStoreValue(store); // will re-render on next value
store.next('next value');useRxStoreDispatcher
type SetStateDispatcher<T> = (state: T | ((current: T) => T)) => void;
function useRxStoreDispatcher<T>(store: ReactRxStore<T>): SetStateDispatcher<T>;Create SetStateDispatcher<T> that dispatch next value to instance of ReactRxStore.
const store = useRxStore('value');
const value = useRxStoreValue(store);
const setValue = useRxStoreDispatcher(store);
setValue(value => `previous was: ${value}`);useRxState
function useRxState<T>(storeInitial: ReactRxStoreInput<T>): [value: T, dispatcher: SetStateDispatcher<T>, store: ReactRxStore<T>];Create and controls instance of ReactRxStore with lifecycle, unless store was passed as initial parameter.
And with this store create useState-like tuple:
- value subscribed to instance of
ReactRxStore, SetStateDispatcher<T>that dispatch next to to instance ofReactRxStore,- and instance of
ReactRxStoreit self.
const [value, setValue, store] = useRxState('value');
setValue(value => `previous was: ${value}`);Or with provided store:
const store: BehaviorSubject<string>;
const [value, setValue] = useRxState(store);
setValue(value => `previous was: ${value}`);useRxStoreObservableFiller
function useRxStoreObservableFiller<T>(
sourceFabric: () => ObservableInput<T>,
deps: DependencyList,
storeInitial?: ReactRxStoreInput<T | undefined>
): ReactRxStore<T | undefined>;Store observable values in rx store.
const store = useRxStoreObservableFiller(() => of(5), []);useRxValue
function useRxValue<T>(sourceFabric: () => BehaviorSubject<T>, deps: DependencyList): T;
function useRxValue<T>(sourceFabric: () => ObservableInput<T>, deps: DependencyList): T | undefined;Subscribe and return value of Observable.
const value: number | undefined = useRxValue(() => of(5).pipe(delay(100)), []);
const value: number | undefined = useRxValue(() => of(5), []);
assert(value, 'value would be equal to \'5\' right away, but typescript can\'t know this for sure');
const value: number = useRxValue(() => new BehaviorSubject(5), []);useRxEventStore
function useRxEventStore<T>(storeInitial: ReactRxStoreInput<T>): [ReactRxStore<T>, (arg: T) => void];
function useRxEventStore<As extends unknown[], T>(
storeInitial: ReactRxStoreInput<T>,
project: (...args: As) => T,
deps: DependencyList
): [ReactRxStore<T>, (...args: As) => void];Creates event handler that stores event value to instance of ReactRxStore.
const [store, handleChange] = useRxEventStore('', (event) => event.target.value);
<input onChange={handleChange} />Or with provided store:
const store: BehaviorSubject<string>;
const [, handleChange] = useRxEventStore(store, (event) => event.target.value);
<input onChange={handleChange} />useRxCallback
function useRxCallback<As extends unknown[], T>(
sourceFabric: (...args: As) => ObservableInput<T>,
deps: DependencyList
): (...args: As) => PromiseSubscribed<T | undefined>;
function useRxCallback<As extends unknown[], T, U>(
sourceFabric: (...args: As) => ObservableInput<T>,
deps: DependencyList,
subscriber: PromiseSubscriber<T, U>
): (...args: As) => PromiseSubscribed<U>;Creates callback that would create and subscribe to Observable returned by sourceFabric and return Promise with resolved value. Can accept subscriber function that can control result of Promise.
Hoist subscribers of toPromise.
Without subsciber would create in lifecycle equivalent of useRxCallback.throttle(useRxCallback.withInitial(undefined, useRxCallback.last<T>())). It means that each call of resulted callback would return last provided value on completion of Observable, would return undefined if value was not provided before completion, and would unsubscribe from Observable created on previous call.
const cb = useRxCallback((count: number) => fromFetch(`https://api.github.com/users?per_page=${count}`), []);
cb(5); // fetch would be canceled, because of next call, and return undefined
const result = await cb(6);API utils
import {} from '@anion155/react-rxjs-hooks/utils';EmptyValueError
class EmptyValueError extends Error;Specific type of Error.
getImmediate
function getImmediate<T>(source: Observable<T>): { value: T } | { error: unknown } | undefined;Get immediate value from Observable.
getImmediate(of(5)); // { value: 5 }
getImmediate(throwError(() => 5)); // { error: 5 }
const subject = new Subject();
subject.complete();
getImmediate(subject); // { error: EmptyValueError }
const subject = new Subject();
getImmediate(subject); // undefinedReactRxStore
interface ReactRxStore<T> extends BehaviorSubject<T> {
reactSubscription: (onStoreChange: () => void) => () => void;
}Store subject with alternative subscription method reactSubscription.
createReactRxStore
type ReactRxStoreInput<T> =
| T
| { (): T }
| BehaviorSubject<T>
| { (): BehaviorSubject<T> };
function createReactRxStore<T>(input: ReactRxStoreInput<T>): ReactRxStore<T>;Creates BehaviorSubject from value (unless not completed instance was provided), use it as prototype (unless it is ReactRxStore already), add reactSubscription implementation.
const store = createReactRxStore('value');
const store = createReactRxStore(() => 'value');
// provided subject is used as prototype
const store = createReactRxStore(new BehaviorSubject('value'));
const store = createReactRxStore(() => new BehaviorSubject('value'));
const completedSubject = new BehaviorSubject('value');
completedSubject.complete();
// only value of subject used
const store = createReactRxStore(completedSubject);
const store = createReactRxStore(() => completedSubject);
const sourceStore = createReactRxStore('value');
// same as sourceStore
const store = createReactRxStore(sourceStore);
const store = createReactRxStore(() => sourceStore);isReactRxStore
function isReactRxStore<T>(subject: BehaviorSubject<T>): subject is ReactRxStore<T>;Checks if subject is ReactRxStore.
isReactRxStore(new BehaviorSubject(5)); // false
isReactRxStore(createReactRxStore(5)); // trueisImmediateCompleted
function isImmediateCompleted<T>(source: Observable<T>): boolean;Checks if Observable is completed without value.
isImmediateCompleted(of(5)); // false
const subject = new Subject();
subject.complete();
isImmediateCompleted(subject); // truetoPromise
type PromiseSubscriber<T, U = T> = (
source: Observable<T>,
resolve: (value: U) => void,
reject: (error: unknown) => void
) => Subscription;
type PromiseSubscribed<T> = Promise<T> & { subscription: Subscription };
function toPromise<T>(source: Observable<T>): PromiseSubscribed<T | undefined>;
function toPromise<T, U>(
source: Observable<T>,
subscriber: PromiseSubscriber<T, U>
): PromiseSubscribed<U>;Creates cancelable Promise from Observable, with attached Subscription instance. Can accept subscriber function that can control result of Promise.
Subscribers:
first<T>(): PromiseSubscriber<T>- returns first value ofObservable, throwsEmptyValueErroron complete;last<T>(): PromiseSubscriber<T>- returns last value ofObservableon complete, if non throwsEmptyValueError;withInitial<T, U, I>(initial: T, subscriber: PromiseSubscriber<T, U>): PromiseSubscriber<T, U | I>- returninitialifEmptyValueErrorwas thrown;throttle<T, U>(subscriber: PromiseSubscriber<T, U>): PromiseSubscriber<T, U>- on call unsubscribe from previous observable;
Without subsciber would use equivalent of toPromise.withInitial(undefined, toPromise.last<T>()). It means that each call of resulted callback would return last provided value on completion of Observable, would return undefined if value was not provided before completion.