SugarCoding
SugarCoding

Reputation: 47

Is it ok to use OnAfterRenderAsync() instead of OnParametersSetAsync() for database calls in Blazor Server?

I am reading that the recommendation is to use OnParametersSetAsync() for any async calls (such as database calls) inside a Blazor server component. The problem though is that OnParametersSetAsync() will fire twice in a default Blazor Server application, and I obviously don't want to access the database twice.

To avoid this problem, some people recommend replacing the "ServerPrerendered" render-mode in _Host.cshtml to "Server", which will avoid OnParametersSetAsync() firing twice. However, I don't like this solution, because the application will take longer to load for the user if we removing the initial static HTML phase.

So, my solution so far has been to put my database access calls inside OnAfterRenderAsync(), and to call StateHasChanged() once I am done. It looks something like this:

public partial class ExampleComponent
{
    [Inject]
    public IUserDataAccess UserAccess { get; set; }

    [Parameter]
    public string UserEmail { get; set; }

    public IUser User { get; set; }

    private bool _isLoading = true;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender == false)
            return;

        User = await UserAccess.GetOneAsync(UserEmail);

        _isLoading = false;
        StateHasChanged();
    }
}

The database call gets made only once, because of the "if (firstRender == false)" condition.

This approach has been working well for me so far, but I suspect that there is something wrong with this way of proceeding, because the examples given online of a valid call to OnAfterRenderAsync() usually only mention JavaScript calls. I don't why that is though. Is there anything wrong with the example code I am giving above? And if this approach is not recommended for some reason, then how can we avoid the double call to the database if we use OnParametersSetAsync() (excluding the server-mode change discussed above)?

Thanks.

Upvotes: 2

Views: 3093

Answers (1)

MrC aka Shaun Curtis
MrC aka Shaun Curtis

Reputation: 30036

Everyone gets hung up on the initial double load and make huge design compromises that they don't need to. [Sorry, and please don't take this the wrong way]This is a probably a good example.

If you're using Blazor Server then, yes the SPA "Start page" gets rendered twice - once on the static first load and once when the SPA starts in the page.

But that's it. Everything after that only gets rendered once. If you are so hung up on that initial load, don't do "too much" in the landing page, make it "light".

To restate - This only happens once, every other routing component load in your SPA only happens once unless you force a re-load or hit F5.

On putting lots of stuff in OnAfterRender{Async}, in general DON'T. It's designed to handle after render activity such as JSInterop stuff. Doing things that then need a call to StateAndChanged is a bit self defeating!

All your once only Db stuff should be in OnInitialized{Async} - normally OnInitializedAsync as it will be async code. You have little control over when OnParametersSet{async} gets run: code in here gets called whenever the component is re-rendered.

Upvotes: 5

Related Questions