0
votes

I have a Blazor server-side page that needs to load data when the user goes to the page. However, after OnAfterRenderAsync executes it does not update the UI. The data is loaded correctly and if I create a "refresh" button to flag the page it works.

I have something like:

@page "/mypage

<button class="btn btn-primary" @onclick="Temp">Refresh</button>

@if (_loading)
{
    <p>
        <em>Loading...</em>
    </p>
}
else
{
    <p>
        <em>Here is your data</em>
    </p>
}

@code {
    private bool _loading { get; set; }
    
    protected override async Task OnInitializedAsync()
    {
        _loading = true;

    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (!firstRender) return;
        //Amazong loading code
        _loading = false;
    }

    private void Temp()
    {
        _loading = false;
    }

}

Stepping through the OnAfterRenderAsync does show that _loading is correctly set to false. Stepping through Temp() does show that _loading is set to false.

I am guessing that OnAfterRenderAsync is not updating the DOM, the fact clicking the button forces an update to the DOM.

2

2 Answers

2
votes

First off, you should load your data in the OnInitialized(Async) pair. If you place code in the OnAfterRender(Async) pair, which change the state of your component, such as: _loading = false;, you should manually call the StateHasChanged method, which notify the component that its state has changed, and that it should re-render.

and if I create a "refresh" button to flag the page it works.

It re-render not because you "flag the page"... In Blazor, UI events, such as the click event automatically calls the StateHasChanged method. When Blazor was at its first phases of development, we had to call the StateHasChanged method manually.

1
votes

The way I would do it is to use OnInitialized event.

For example if you are loading a list of categories you could apply the following test conditions in the razor markup:

@if (categories == null && _loadFailed)
{
    <h1 class="text-danger">The data has failed to load please try again in a little bit..</h1>
}
else if (categories == null)
{
    <h1 class="text-success">Loading...</h1>
    <div style="display:normal;margin:auto" class="loader"></div>
}
else if (categories.Count == 0)
{
    <text>No categories found</text>
}
else...