JAVASCRIPT

Managing Async Operations and Data Fetching with useAsync Hook

Create a robust custom React hook to handle asynchronous operations, providing loading, error, and data states for cleaner and more reusable data fetching logic.

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);

  const execute = useCallback(() => {
    setStatus('pending');
    setValue(null);
    setError(null);
    return asyncFunction()
      .then((response) => {
        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 UserProfile({ userId }) {
//   const fetchUser = useCallback(async () => {
//     const response = await fetch(`https://api.example.com/users/${userId}`);
//     if (!response.ok) {
//       throw new Error('Failed to fetch user');
//     }
//     return response.json();
//   }, [userId]);

//   const { execute, status, value: user, error } = useAsync(fetchUser, true);

//   if (status === 'pending') return <div>Loading user...</div>;
//   if (status === 'error') return <div>Error: {error.message}</div>;
//   if (status === 'success' && user) {
//     return (
//       <div>
//         <h2>{user.name}</h2>
//         <p>{user.email}</p>
//         <button onClick={execute}>Refresh User</button>
//       </div>
//     );
//   }
//   return null;
// }
How it works: The `useAsync` hook streamlines the management of asynchronous operations, such as data fetching. It provides `status` (idle, pending, success, error), `value` (the resolved data), and `error` states, reducing boilerplate in components. The `execute` function can be called manually to trigger the async operation. When `immediate` is true, the function runs on mount. This pattern makes handling loading states, errors, and data much cleaner and reusable across your application.

Need help integrating this into your project?

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

Hire DigitalCodeLabs