Fetch data with React hooks and RxJS. Inspired by react-async
const state = useRxAsync(asyncFn, options?);| 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 |
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));| 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 |
const delay = (ms: number) => new Promise(_ => setTimeout(_, ms));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;
}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]);
}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);
// ....
}const { data } = useRxAsync(apiRequest, {
initialValue: [],
});
// or
const { data = [] } = useRxAsync(apiRequest);If you are axios user, you could use kuitos/axios-extensions