import useAsync from './useAsync';
export const wait5Seconds = new Promise(
resolve => window.setTimeout(resolve, 5000)
)
export default () => {
const { resolve, loading } = useAsync({ promise: wait5Seconds })
return (
<button onClick={resolve} disabled={loading}>
{loading ? 'Waiting...' : 'Wait'}
</button>
)
};
Last active
February 3, 2021 10:56
-
-
Save fernandocamargo/a91df8b0cc6508b62de28a27dc801ce5 to your computer and use it in GitHub Desktop.
Trust no one
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import noop from 'lodash/noop'; | |
export const PENDING = new Promise(noop); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { PENDING } from './constants'; | |
export class Validity { | |
constructor() { | |
this.stale = false; | |
} | |
expire = () => { | |
this.stale = true; | |
}; | |
succeed = (...params) => (!this.stale ? Promise.resolve(...params) : PENDING); | |
fail = (...params) => (!this.stale ? Promise.reject(...params) : PENDING); | |
check = promise => { | |
const { succeed, fail } = this; | |
return promise.then(succeed).catch(fail); | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const getInitialState = () => ({ | |
loading: false, | |
data: null, | |
error: null, | |
}); | |
export const attempt = () => () => ({ loading: true, data: null, error: null }); | |
export const succeed = data => () => ({ loading: false, error: null, data }); | |
export const fail = error => () => ({ loading: false, data: null, error }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useCallback, useEffect, useRef, useState } from 'react'; | |
import { attempt, fail, getInitialState, succeed } from './reducers'; | |
import { Validity } from './helpers'; | |
export default ({ promise }) => { | |
const { current: controller } = useRef(new AbortController()); | |
const [state, setState] = useState(getInitialState()); | |
const resolve = useCallback( | |
(...params) => { | |
const { check, expire } = new Validity(); | |
const abort = () => controller.abort(); | |
new Promise((resolve, reject) => | |
check(promise(...params)) | |
.then(data => { | |
setState(succeed(data)); | |
return resolve(data); | |
}) | |
.catch(error => { | |
setState(fail(error)); | |
return reject(error); | |
}) | |
.finally(() => controller.signal.removeEventListener('abort', expire)) | |
); | |
controller.signal.addEventListener('abort', expire); | |
setState(attempt({ params })); | |
return abort; | |
}, | |
[promise, controller] | |
); | |
useEffect(() => () => controller.abort(), [controller]); | |
return { ...state, resolve }; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment