JAVASCRIPT

Generic useAsync Hook for Managing Asynchronous Operations

Develop a flexible React `useAsync` hook to manage the lifecycle of any promise-based asynchronous operation, handling loading, success, and error states gracefully.

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

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

  // The asyncFunction is wrapped in useCallback to prevent infinite loops
  // if it's defined inline in the component using useAsync.
  const execute = useCallback(async (...args) => {
    setStatus('pending');
    setValue(null);
    setError(null);
    try {
      const response = await asyncFunction(...args);
      setValue(response);
      setStatus('success');
    } catch (err) {
      setError(err);
      setStatus('error');
    }
  }, [asyncFunction]);

  useEffect(() => {
    if (immediate) {
      execute();
    }
  }, [execute, immediate]);

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

// Example Usage:
// function DataFetcher() {
//   const simulateDataFetch = () => {
//     return new Promise((resolve, reject) => {
//       setTimeout(() => {
//         const success = Math.random() > 0.5;
//         if (success) {
//           resolve({ data: 'This is fetched data!' });
//         } else {
//           reject(new Error('Failed to fetch data.'));
//         }
//       }, 1500);
//     });
//   };

//   const { execute, status, value, error } = useAsync(simulateDataFetch, true);

//   return (
//     <div>
//       {status === 'idle' && <p>Ready to fetch data.</p>}
//       {status === 'pending' && <p>Loading...</p>}
//       {status === 'success' && <p>Data: {value.data}</p>}
//       {status === 'error' && <p>Error: {error.message}</p>}
//       <button onClick={execute} disabled={status === 'pending'}>
//         Refetch Data
//       </button>
//     </div>
//   );
// }
How it works: This `useAsync` hook is a powerful pattern for managing the state of any promise-based asynchronous operation within React components. It tracks `status` (idle, pending, success, error), `value` (the resolved data), and `error` (if the promise rejects). The `execute` function allows you to trigger the async operation. By using `useEffect` with an `immediate` flag, the operation can be run automatically on component mount. This hook centralizes async logic, making components cleaner and easier to manage by separating concerns.

Need help integrating this into your project?

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

Hire DigitalCodeLabs