Back to Roadmap
6:00

Async State Handling

Learn how to manage loading, success, and error states when working with asynchronous data in React

6 MIN READ VERIFIED CURRICULUM

Async state handling in React refers to managing UI states when dealing with asynchronous operations like API calls, timers, or data fetching.

Since these operations do not complete immediately, React applications must handle loading, success, and error states properly.

What is Async State?

Async state represents data that is being fetched or processed over time rather than being immediately available.

It typically includes three main states: loading, success, and error.

Why Async State Handling is Important

Without proper async state handling, users may see blank screens or broken interfaces while data is loading.

Good async handling improves user experience by providing feedback during data fetching.

Basic Async State Structure

A common pattern is to use multiple pieces of state to track loading, data, and errors.

const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
javascript

Fetching Data with Async State

When making API calls, you should update loading state before and after the request.

useEffect(() => {
  async function fetchData() {
    setLoading(true);
    setError(null);

    try {
      const res = await fetch('https://api.example.com/data');
      const result = await res.json();
      setData(result);
    } catch (err) {
      setError('Failed to fetch data');
    } finally {
      setLoading(false);
    }
  }

  fetchData();
}, []);
javascript

Handling Loading State

Loading state is used to show users that a request is in progress.

This can be implemented using spinners, skeletons, or simple text indicators.

if (loading) return <p>Loading data...</p>;
javascript

Handling Error State

Error state helps display meaningful messages when something goes wrong during data fetching.

This improves debugging and user experience.

if (error) return <p>{error}</p>;
javascript

Handling Success State

Success state is when data is successfully fetched and ready to be displayed.

return (
  <ul>
    {data?.map(item => (
      <li key={item.id}>{item.name}</li>
    ))}
  </ul>
);
javascript

State Flow in Async Operations

The typical flow of async state is: loading starts, request is made, success or error occurs, and loading ends.

This flow ensures predictable UI behavior.

Using Async/Await Cleanly

Async/await makes asynchronous code easier to read and manage compared to chained promises.

async function fetchData() {
  setLoading(true);
  try {
    const res = await fetch('https://api.example.com/data');
    const data = await res.json();
    setData(data);
  } catch (err) {
    setError(err.message);
  } finally {
    setLoading(false);
  }
}
javascript

Avoiding Common Mistakes

A common mistake is not resetting error or loading states properly between requests.

Another issue is updating state after a component has unmounted.

Real-World Usage

Async state handling is widely used in dashboards, authentication flows, product listings, and real-time applications.

It ensures users always receive feedback during data operations.

Best Practices

Always manage loading, error, and success states explicitly.

Consider using custom hooks to reuse async logic across components.

Summary

Async state handling is essential for building reliable and user-friendly React applications.

Proper management of loading, error, and success states ensures smooth user experiences.