'Blazor Webassembly lifecycle events called twice after NavigationManager.NavigateTo [duplicate]

On the load of a page (Blazor WebAssembly - NOT server), I do this:

protected override Task OnInitializedAsync()
{
    Console.WriteLine("Initialised");
    return base.OnInitializedAsync();
}

On first load, this is called once. After I call:

NavigationManager.NavigateTo("/anotherpage");

With the same OnInitializedAsync code above - it is called twice on that page. Making it really difficult to only load data from an API once.

I have read a lot about lifecycle events like OnInitializedAsync being called twice when the render mode for Blazor is set to ServerPreRendered - however this is a wasm project, and so there is no prerendering, and I'm stumped

Update: Further investigation has lead to the page layout actually being the culprit (as described in this bug: github.com/dotnet/aspnetcore/issues/20637). This question also describes it - but leaving this question here incase someone has the same issue I did



Solution 1:[1]

I tried your code in my side and here what I've found:

  • You should have await base.OnInitializedAsync(); instead of return base.OnInitializedAsync(); -> using your version does not let me to build.

  • I've created the following Blazor page:

@page "/fetchdata"
@inject NavigationManager NavigationManager

<button @onclick="OnClick">CLICK</button>

@code {

    protected override async Task OnInitializedAsync()
    {
        Console.WriteLine("Initialised");
        await base.OnInitializedAsync();
    }

    public void OnClick()
    {
        NavigationManager.NavigateTo("/fetchdata");
    }
}

I put a breakpoint in the OnInitializedAsync method. It is hitten on the loading of the page, but not when I clicked on the button. So I assume you do this call outside the page with this issue. So we'll need this part too, because I've tried this solution too (button and call in another page), same result.

Solution 2:[2]

This is my test setup to try and emulate your problem. As I expected, OnInitialized is only run once per page load. Therefore there must be something else on your pages that is causing the problem. What extra do you have on your pages?

First.razor

@page "/First"
@inject NavigationManager NavManager
@using System.Text

<div>
    <button @onclick=this.ClickMe> Click Me </button>
</div>

<div class="m-2">
    <pre>
        @sb.ToString()
    </pre>
</div>
@code {
    private Guid Id = Guid.NewGuid();
    private StringBuilder sb = new StringBuilder();

    protected override void OnInitialized()
    {
        var message = $"OnInitialized on Component {this.Id.ToString().Substring(32)} ran at {DateTime.Now.ToLongTimeString()}";
        Console.WriteLine(message);
        sb.AppendLine(message);
        base.OnInitialized();
    }

    private void ClickMe(MouseEventArgs e)
    {
        this.NavManager.NavigateTo("/Second");
    }
}

Second.razor

@page "/Second"
@inject NavigationManager NavManager
@using System.Text

<div>
    <button @onclick=this.ClickMe> Click Me </button>
</div>

<div class="m-2">
    <pre>
        @sb.ToString();
    </pre>
</div>
@code {
    private Guid Id = Guid.NewGuid();
    private StringBuilder sb = new StringBuilder();

    protected override void OnInitialized()
    {
        var message = $"OnInitialized on Component {this.Id.ToString().Substring(32)} ran at {DateTime.Now.ToLongTimeString()}";
        Console.WriteLine(message);
        sb.AppendLine(message);
        base.OnInitialized();
    }

    private void ClickMe(MouseEventArgs e)
    {
        this.NavManager.NavigateTo("/First");
    }
}

And the results in the console:

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dylan Barquilla
Solution 2