Home > Blockchain >  Blazor OnAfterRenderAsync Confusion
Blazor OnAfterRenderAsync Confusion

Time:08-25

I understand the idea of OnAfterRenderAsyc but I don't understand how to implement what I want. I have OnInitializedAsync that basically gets a summary information from files. After that I want to call 2 other methods and based on information returned from those 2 methods I want to add some HTML into my component. So far I have this

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            driveFiles = await DriveService.GetList(true);
            permissionFiles = await DriveService.GetPermissions();
            
        }
        await base.OnAfterRenderAsync(firstRender);
    }

I then just want to add some basic HTML after OnAfterRenderAsync has happened, something like

    @foreach (var file in driveFiles.Select((value, index) => new {value, index}))
    {
        <p>
            Name: @file.value.FileName
        <br />
            File Id: @file.value.FileId
        <br />
            File Number: @file.index 
        </p>
        <hr />
    }

How do I do that? I can't find anything on google that explains how to actually use OnAfterRenderAsync, they just explain the basic ideas behind it. I'm sure I am overthinking it but I can't figure it out

CodePudding user response:

When invoking asynchronous methods in OnInitializedAsync the UI will be rendered twice. Once when the first await is encountered and again when OnInitializedAsync completes. This enables the component to render mark-up for the user to see whilst it performs background tasks such as retrieving data from a server.

You can also see this behaviour in the following chart of the lifecycle of a blazor component (from microsoft documentation).

lifecycle

During the first render if you try to display your data you will get a null reference exception because the asynchronous task has not completed yet.

The solution is to wrap your ui code inside an if statement:

@if (driveFiles != null)
{
    @foreach (var file in driveFiles.Select((value, index) => new {value, index}))
    {
        <p>
            Name: @file.value.FileName
        <br />
            File Id: @file.value.FileId
        <br />
            File Number: @file.index 
        </p>
        <hr />
    }
}
else
{
    @* Show a loading indicator *@
    <p>Loading...</p>
}

For your scenario you actually don't need to use OnAfterRenderAsync method.

Sources:

  1. microsoft documentation
  2. https://jonhilton.net/when-does-blazor-render-your-ui/
  3. https://blazor-university.com/components/component-lifecycles/
  • Related