Course contentsShow
← C#
Lesson 1330 of 1,90812. Modern Frontend with Razor and BlazorFree lesson

Asynchronous Data Loading Patterns

Fetch data from external APIs using HttpClient while displaying loading states.

In this lesson, you will learn how to create a responsive user experience by fetching remote data asynchronously while gracefully managing "loading" states in your Blazor components.

The Challenge of Latency

When your application requests data from an external API, the operation isn't instantaneous. If you simply block the UI thread waiting for the data, the page will appear frozen. In Blazor, the standard pattern is to initialize the component with a null or empty state, trigger an asynchronous task, and update the UI once the data arrives.

Implementing the Pattern

To handle this, we use the OnInitializedAsync lifecycle method. By setting a private field (e.g., isLoading) to true before the request and false after the await completes, we can provide immediate visual feedback to the user.

@inject HttpClient Http

@if (forecasts == null)
{
    <p><em>Loading your data...</em></p>
}
else
{
    <ul>
        @foreach (var item in forecasts) { <li>@item.Summary</li> }
    </ul>
}

@code {
    private WeatherForecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
        // Data fetching happens here without blocking the initial render
        forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("api/weather");
    }
}

Why this approach works

  1. Initial Render: Blazor renders the component immediately, hits the if (forecasts == null) block, and displays the "Loading" message.
  2. Background Execution: The HttpClient request runs asynchronously. The component does not hold up the rendering pipeline.
  3. Re-rendering: Once forecasts is populated, calling await (or simply the completion of the async method) triggers a re-render. Blazor detects the state change and swaps the "Loading" text for the actual data list.

This pattern keeps your UI interactive, ensuring that users aren't left wondering if the application has crashed while the network request is in flight. By using simple conditional logic combined with lifecycle methods, you bridge the gap between "request sent" and "data received."

Key Takeaway: Always use an explicit loading state variable or check for null collections to provide visual feedback while waiting for asynchronous API responses.