mirror of
https://github.com/streamich/react-use.git
synced 2025-12-08 18:02:14 +00:00
feat: 🎸 add usePromise() hook
This commit is contained in:
parent
a2a6fe326a
commit
aad368ba67
@ -76,6 +76,7 @@
|
||||
- [**Lifecycles**](./docs/Lifecycles.md)
|
||||
- [`useLifecycles`](./docs/useLifecycles.md) — calls `mount` and `unmount` callbacks.
|
||||
- [`useRefMounted`](./docs/useRefMounted.md) — tracks if component is mounted.
|
||||
- [`usePromise`](./docs/usePromise.md) — resolves promise only while component is mounted.
|
||||
- [`useLogger`](./docs/useLogger.md) — logs in console as component goes through life-cycles.
|
||||
- [`useMount`](./docs/useMount.md) — calls `mount` callbacks.
|
||||
- [`useUnmount`](./docs/useUnmount.md) — calls `unmount` callbacks.
|
||||
|
||||
24
docs/usePromise.md
Normal file
24
docs/usePromise.md
Normal file
@ -0,0 +1,24 @@
|
||||
# `usePromise`
|
||||
|
||||
React Lifecycle hook that returns a helper function for wrapping promises.
|
||||
Promises wrapped with this function will resolve only when component is mounted.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```jsx
|
||||
import {usePromise} from 'react-use';
|
||||
|
||||
const Demo = ({promise}) => {
|
||||
const mounted = usePromise();
|
||||
const [value, setValue] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const value = await mounted(promise);
|
||||
// This line will not execute if <Demo> component gets unmounted.
|
||||
setValue(value);
|
||||
})();
|
||||
});
|
||||
};
|
||||
```
|
||||
42
src/__stories__/usePromise.story.tsx
Normal file
42
src/__stories__/usePromise.story.tsx
Normal file
@ -0,0 +1,42 @@
|
||||
import {storiesOf} from '@storybook/react';
|
||||
import * as React from 'react';
|
||||
import {usePromise, useBoolean, useNumber} from '..';
|
||||
import ShowDocs from '../util/ShowDocs';
|
||||
|
||||
const {useState, useEffect} = React;
|
||||
|
||||
const DemoInner = ({promise}) => {
|
||||
const safePromise = usePromise();
|
||||
const [value, setValue] = useState<number>(-1);
|
||||
useEffect(() => {
|
||||
safePromise(promise).then(setValue);
|
||||
}, [promise]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{value === -1 ? 'Resolving value...' : 'Value: ' + value}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Demo = () => {
|
||||
const [mounted, toggleMounted] = useBoolean(true);
|
||||
const [num, {inc}] = useNumber();
|
||||
const promise = new Promise(r => setTimeout(() => r(num), 1_000));
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>This demo provides a number in a promise that resolves in 1sec to a child component.</p>
|
||||
<button onClick={() => toggleMounted()}>{mounted ? 'Unmount' : 'Mount'}</button>
|
||||
<button onClick={() => inc()}>Increment ({num})</button>
|
||||
<br />
|
||||
{mounted && <DemoInner promise={promise} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
storiesOf('Lifecycles|usePromise', module)
|
||||
.add('Docs', () => <ShowDocs md={require('../../docs/usePromise.md')} />)
|
||||
.add('Demo', () =>
|
||||
<Demo/>
|
||||
)
|
||||
@ -30,6 +30,7 @@ import useNumber from './useNumber';
|
||||
import useObservable from './useObservable';
|
||||
import useOrientation from './useOrientation';
|
||||
import useOutsideClick from './useOutsideClick';
|
||||
import usePromise from './usePromise';
|
||||
import useRaf from './useRaf';
|
||||
import useRefMounted from './useRefMounted';
|
||||
import useSessionStorage from './useSessionStorage';
|
||||
@ -80,6 +81,7 @@ export {
|
||||
useObservable,
|
||||
useOrientation,
|
||||
useOutsideClick,
|
||||
usePromise,
|
||||
useRaf,
|
||||
useRefMounted,
|
||||
useSessionStorage,
|
||||
|
||||
22
src/usePromise.ts
Normal file
22
src/usePromise.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import {useCallback} from 'react';
|
||||
import useRefMounted from './useRefMounted';
|
||||
|
||||
export type UsePromise = () => <T>(promise: Promise<T>) => Promise<T>;
|
||||
|
||||
const usePromise: UsePromise = () => {
|
||||
const refMounted = useRefMounted();
|
||||
return useCallback(<T>(promise: Promise<T>): Promise<T> =>
|
||||
new Promise<T>((resolve, reject) => {
|
||||
promise.then(value => {
|
||||
if (refMounted.current) {
|
||||
resolve(value);
|
||||
}
|
||||
}, error => {
|
||||
if (refMounted.current) {
|
||||
reject(error);
|
||||
}
|
||||
})
|
||||
}), []);
|
||||
};
|
||||
|
||||
export default usePromise;
|
||||
Loading…
x
Reference in New Issue
Block a user