Last active
February 17, 2024 16:42
-
-
Save gragland/33b5d146891c77ceb1f3493a2428f026 to your computer and use it in GitHub Desktop.
React Hook recipe from https://usehooks.com
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 React, { useState, useEffect, useCallback } from 'react'; | |
// Usage | |
function App() { | |
const { execute, status, value, error } = useAsync(myFunction, false); | |
return ( | |
<div> | |
{status === 'idle' && <div>Start your journey by clicking a button</div>} | |
{status === 'success' && <div>{value}</div>} | |
{status === 'error' && <div>{error}</div>} | |
<button onClick={execute} disabled={status === 'pending'}> | |
{status !== 'pending' ? 'Click me' : 'Loading...'} | |
</button> | |
</div> | |
); | |
} | |
// An async function for testing our hook. | |
// Will be successful 50% of the time. | |
const myFunction = () => { | |
return new Promise((resolve, reject) => { | |
setTimeout(() => { | |
const rnd = Math.random() * 10; | |
rnd <= 5 | |
? resolve('Submitted successfully 🙌') | |
: reject('Oh no there was an error 😞'); | |
}, 2000); | |
}); | |
}; | |
// Hook | |
const useAsync = (asyncFunction, immediate = true) => { | |
const [status, setStatus] = useState('idle'); | |
const [value, setValue] = useState(null); | |
const [error, setError] = useState(null); | |
// The execute function wraps asyncFunction and | |
// handles setting state for pending, value, and error. | |
// useCallback ensures the below useEffect is not called | |
// on every render, but only if asyncFunction changes. | |
const execute = useCallback(() => { | |
setStatus('pending'); | |
setValue(null); | |
setError(null); | |
return asyncFunction() | |
.then(response => { | |
setValue(response); | |
setStatus('success'); | |
}) | |
.catch(error => { | |
setError(error); | |
setStatus('error'); | |
}); | |
}, [asyncFunction]); | |
// Call execute if we want to fire it right away. | |
// Otherwise execute can be called later, such as | |
// in an onClick handler. | |
useEffect(() => { | |
if (immediate) { | |
execute(); | |
} | |
}, [execute, immediate]); | |
return { execute, status, value, error }; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The init value of state should be depend on immediate variable:
const [status, setStatus] = useState(() => immediate ? 'pending' : 'idle' );