Skip to content
This repository has been archived by the owner on Dec 26, 2019. It is now read-only.

Pong420/useRxAsync

Repository files navigation

useRxAsync

See Pong420/use-rx-hooks


Fetch data with React hooks and RxJS. Inspired by react-async

const state = useRxAsync(asyncFn, options?);

State

name description
data The value return from asyncFn
loading boolean
error any, depends on your asyncFn
cancel ignore the new value return from your asyncFn
reset reset data, loading, error to initialValue

AsyncFn

A function that return PromiseLike or Observable. For examples,

const delay = (ms: number) => new Promise(_ => setTimeout(_, ms));
const rxAsyncFn = (result: string) => timer(1000).pipe(map(() => result));

Options

option description
initialValue set the initial value of your asyncFn
defer by default, your asyncFn will be call at initial or it changed. if you set defer to true, it will only run when you execute the run mehtod
onStart callback when asyncFn start, () => void
onSuccess callback when asyncFn success, (result) => void
onFaulure callback when asyncFn failure, (error: any) => void
mapOperator switchMap, concatMap , exhaustMap , mergeMap , flatMap, default is switchMap

Recipes

const delay = (ms: number) => new Promise(_ => setTimeout(_, ms));

Basic

Examples

import { useRxAsync } from 'use-rx-async';

function Component() {
  const { data, loading, error, cancel, reset } = useRxAsync(asyncFn);

  if (loading) {
    return 'loading...';
  }

  if (error) {
    return 'error!';
  }

  return data;
}

AsyncFn with dynamic parameters

Examples

const asyncFnWithParam = (result: string) => delay(1000).then(() => result);

// wrap your default asyncFn with useCallback
function useHooks() {
  const [result, setResult] = useState<string>();
  const asyncFn = useCallback(() => {
    return typeof result === 'string'
      ? asyncFnWithParam(result)
      : Promise.reject();
  }, [result]);
  const { loading, data } = useRxAsync(asyncFn);

  useEffect(() => {
    setResult('Hello world');
  }, []);
}

// Or set `defer` to true, if the asyncFn has parameters, you cannot set defer to false / undefined.
function useHooks() {
  const { run } = useRxAsync(asyncFnWithParam, { defer: true });
  useEffect(() => {
    run('Hello World');
  }, [run]);
}

With RxJS operators

import { timer } from 'rxjs';
import { delayWhen, retryWhen, take } from 'rxjs/operators';

const yourApiRequest = () => fetch('/api').then(res => res.json());

// if the request has errors, delay 1 second then retry up to 3 times
const asyncFn = () =>
  from(yourApiRequest()).pipe(
    retryWhen(errors =>
      errors.pipe(
        switchMap((error, index) =>
          index === 3 ? throwError(error) : of(error)
        ),
        delayWhen(() => timer(1000))
      )
    )
  );

function Component() {
  const state = useRxAsync(asyncFn);

  // ....
}

With initial value

const { data } = useRxAsync(apiRequest, {
  initialValue: [],
});

// or

const { data = [] } = useRxAsync(apiRequest);

Caching

If you are axios user, you could use kuitos/axios-extensions

More React hooks with RxJS

License

MIT