mirror of
https://github.com/streamich/react-use.git
synced 2026-01-25 14:17:16 +00:00
useAsyncCallback
This commit is contained in:
parent
a48d57cccb
commit
22682c176c
@ -73,6 +73,7 @@
|
||||
<br/>
|
||||
- [**Side-effects**](./docs/Side-effects.md)
|
||||
- [`useAsync`](./docs/useAsync.md) — resolves an `async` function.
|
||||
- [`useAsyncCallback`](./docs/useAsyncCallback.md) — state management for async callback
|
||||
- [`useAsyncRetry`](./docs/useAsyncRetry.md) — `useAsync` with `retry()` method.
|
||||
- [`useCopyToClipboard`](./docs/useCopyToClipboard.md) — copies text to clipboard.
|
||||
- [`useDebounce`](./docs/useDebounce.md) — debounces a function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/side-effects-usedebounce--demo)
|
||||
|
||||
36
docs/useAsyncCallback.md
Normal file
36
docs/useAsyncCallback.md
Normal file
@ -0,0 +1,36 @@
|
||||
# `useAsyncCallback`
|
||||
|
||||
React hook that returns state and a callback for an `async` function or a
|
||||
function that returns a promise. The state is of the same shape as `useAsync`.
|
||||
|
||||
## Usage
|
||||
|
||||
```jsx
|
||||
import {useAsyncCallback} from 'react-use';
|
||||
|
||||
const Demo = (url) => {
|
||||
const [state, fetch] = useAsyncCallback(async () => {
|
||||
const response = await fetch(url);
|
||||
const result = response.text();
|
||||
return result
|
||||
}), [url];
|
||||
|
||||
return (
|
||||
<div>
|
||||
{state.loading
|
||||
? <div>Loading...</div>
|
||||
: state.error
|
||||
? <div>Error: {state.error.message}</div>
|
||||
: state.value && <div>Value: {state.value}</div>
|
||||
}
|
||||
<button onClick={() => fetch()}>Start loading</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
```ts
|
||||
useAsyncCallback(fn, deps?: any[]);
|
||||
```
|
||||
35
src/__stories__/useAsyncCallback.story.tsx
Normal file
35
src/__stories__/useAsyncCallback.story.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import * as React from 'react';
|
||||
import {storiesOf} from '@storybook/react';
|
||||
import {useAsyncCallback} from '..';
|
||||
import ShowDocs from './util/ShowDocs';
|
||||
|
||||
const fn = () =>
|
||||
new Promise<string>((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
if (Math.random() > 0.5) {
|
||||
reject(new Error('Random error!'));
|
||||
} else {
|
||||
resolve('RESOLVED');
|
||||
}
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
const Demo = () => {
|
||||
const [{loading, error, value}, callback] = useAsyncCallback<string>(fn);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{loading
|
||||
? <div>Loading...</div>
|
||||
: error
|
||||
? <div>Error: {error.message}</div>
|
||||
: value && <div>Value: {value}</div>
|
||||
}
|
||||
<button onClick={() => callback()}>Start</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
storiesOf('Side effects|useAsyncCallback', module)
|
||||
.add('Docs', () => <ShowDocs md={require('../../docs/useAsyncCallback.md')} />)
|
||||
.add('Demo', () => <Demo/>)
|
||||
@ -1,5 +1,6 @@
|
||||
import createMemo from './createMemo';
|
||||
import useAsync from './useAsync';
|
||||
import useAsyncCallback from './useAsyncCallback';
|
||||
import useAsyncRetry from './useAsyncRetry';
|
||||
import useAudio from './useAudio';
|
||||
import useBattery from './useBattery';
|
||||
@ -71,6 +72,7 @@ import useUpdateEffect from './useUpdateEffect'
|
||||
export {
|
||||
createMemo,
|
||||
useAsync,
|
||||
useAsyncCallback,
|
||||
useAsyncRetry,
|
||||
useAudio,
|
||||
useBattery,
|
||||
|
||||
48
src/useAsyncCallback.ts
Normal file
48
src/useAsyncCallback.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { useState, useEffect, useCallback, DependencyList } from 'react';
|
||||
import useRefMounted from "./useRefMounted"
|
||||
|
||||
export type AsyncState<T> =
|
||||
| {
|
||||
loading: boolean;
|
||||
error?: undefined;
|
||||
value?: undefined;
|
||||
}
|
||||
| {
|
||||
loading: false;
|
||||
error: Error;
|
||||
value?: undefined;
|
||||
}
|
||||
| {
|
||||
loading: false;
|
||||
error?: undefined;
|
||||
value: T;
|
||||
};
|
||||
|
||||
const useAsyncCallback = <T>(fn: () => Promise<T>, deps: DependencyList = []): [AsyncState<T>, () => void] => {
|
||||
const [state, set] = useState<AsyncState<T>>({
|
||||
loading: false
|
||||
});
|
||||
|
||||
const mounted = useRefMounted();
|
||||
|
||||
const callback = useCallback(() => {
|
||||
set({loading: true});
|
||||
|
||||
fn().then(
|
||||
value => {
|
||||
if (mounted.current) {
|
||||
set({value, loading: false});
|
||||
}
|
||||
},
|
||||
error => {
|
||||
if (mounted.current) {
|
||||
set({error, loading: false});
|
||||
}
|
||||
}
|
||||
);
|
||||
}, deps);
|
||||
|
||||
return [state, callback]
|
||||
};
|
||||
|
||||
export default useAsyncCallback;
|
||||
Loading…
x
Reference in New Issue
Block a user