JAVASCRIPT

Simplify Async Operations with useAsync React Hook

Build a versatile useAsync React hook to manage asynchronous data fetching or any promise-based operation, gracefully handling loading states, successful data, and errors.

import { useState, useEffect, useCallback } from 'react';

function useAsync(asyncFunction, immediate = true) {
  const [status, setStatus] = useState('idle');
  const [value, setValue] = useState(null);
  const [error, setError] = useState(null);

  // The execute function calls the async function and sets the state
  // We use useCallback to memoize the function, preventing unnecessary re-renders
  // if it's passed down to child components.
  const execute = useCallback(() => {
    setStatus('pending');
    setValue(null);
    setError(null);
    return asyncFunction()
      .then((response) => {
        setValue(response);
        setStatus('success');
      })
      .catch((err) => {
        setError(err);
        setStatus('error');
      });
  }, [asyncFunction]);

  // Call execute if we want to fire it right away.
  // Otherwise, the caller can execute it themselves.
  useEffect(() => {
    if (immediate) {
      execute();
    }
  }, [execute, immediate]);

  return { execute, status, value, error };
}

// Example Usage:
// function DataFetcher() {
//   const fetchData = useCallback(() => {
//     return new Promise((resolve) => {
//       setTimeout(() => resolve('Data fetched!'), 2000);
//     });
//   }, []);
//
//   const { execute, status, value, error } = useAsync(fetchData, false);
//
//   if (status === 'idle') {
//     return <button onClick={execute}>Start Fetching</button>;
//   }
//
//   if (status === 'pending') {
//     return <p>Loading...</p>;
//   }
//
//   if (status === 'error') {
//     return <p>Error: {error.message}</p>;
//   }
//
//   if (status === 'success') {
//     return <p>Success: {value}</p>;
//   }
// }
How it works: The `useAsync` hook streamlines the process of managing asynchronous operations (like API calls) within React components. It takes an `asyncFunction` (which should return a Promise) and an optional `immediate` flag. The hook provides `status` (`idle`, `pending`, `success`, `error`), `value` (resolved data), `error` (rejection reason), and an `execute` function to trigger the async operation. This centralizes state management for asynchronous flows, making components cleaner and more robust.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs