JAVASCRIPT
Manage Asynchronous Operations with useAsync
A powerful React hook to manage the lifecycle of any asynchronous operation, handling loading, error, and data states for cleaner UI and better user experience.
import { useState, useEffect, useCallback } from 'react';
const useAsync = (asyncFunction, immediate = false) => {
const [status, setStatus] = useState('idle');
const [value, setValue] = useState(null);
const [error, setError] = useState(null);
const execute = useCallback(() => {
setStatus('pending');
setValue(null);
setError(null);
return asyncFunction()
.then(response => {
setValue(response);
setStatus('success');
})
.catch(error => {
setError(error);
setStatus('error');
});
}, [asyncFunction]);
useEffect(() => {
if (immediate) {
execute();
}
}, [execute, immediate]);
return { execute, status, value, error };
};
export default useAsync;
/*
// Example Usage:
const fetchUserData = () => new Promise(resolve => {
setTimeout(() => resolve({ name: 'John Doe', age: 30 }), 2000);
});
function UserProfile() {
const { execute, status, value, error } = useAsync(fetchUserData, true);
return (
<div>
{status === 'pending' && <p>Loading user data...</p>}
{status === 'error' && <p>Error: {error ? error.message : 'Unknown error'}</p>}
{status === 'success' && value && (
<p>Name: {value.name}, Age: {value.age}</p>
)}
<button onClick={execute} disabled={status === 'pending'}>
{status === 'pending' ? 'Loading...' : 'Refresh User'}
</button>
</div>
);
}
*/
How it works: The `useAsync` hook provides a structured way to manage asynchronous operations by tracking their `status` ('idle', 'pending', 'success', 'error'), `value`, and `error`. It accepts an `asyncFunction` (a function that returns a Promise) and an `immediate` flag. The `execute` function can be called manually to trigger the operation, or it runs automatically on mount if `immediate` is true. This pattern simplifies displaying loading states, error messages, and fetched data from any Promise-based source.