Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blazor UriHelper.NavigateTo is calling the page twice

Tags:

blazor

I created a new Blazor Server Side Application in Preview 8. When I call the UriHelper.NavigateTo to go to the counter page from the Index.razor page, the counter page is called twice.

In the Index.razor page I have this code:

@code{

    protected async override Task OnInitializedAsync()
    {
        UriHelper.NavigateTo("/counter");
    }

}

Then in the counter page I added the following code with a breakpoint in it:

protected override void OnInitialized()
{

}

My expectation is to call the counter page only one time when the NavigateTo calls the counter route in the Index.razor

like image 341
user9402642 Avatar asked Aug 27 '19 19:08

user9402642


People also ask

How do you navigate to another page in Blazor with parameter?

By using Blazor route parameters, you can pass values from one page to another page. Use NavigationManager to pass a value and route the parameter to another page. Follow this example to achieve passing values from one page to another. Get the passed Page1 parameter value in Page2.

How do I get the current URL in Blazor?

Inject NavigationManager in razor. Use Uri from NavigationManager to get the current URL.

What is App razor in Blazor?

Razor components are units of markup and code that represent the basic UI elements of any Blazor app implemented with a . razor extension. In other words, Blazor uses Razor components to create UIs, meaning you can write Razor components and utilize Blazor as the client-side hosting model for them.

How do you navigate Blazor?

You can redirect to a page in Blazor using the Navigation Manager's NavigateTo method. In the following code snippet, it will redirect to the home page when this page gets loaded. Similarly, you can call NavigateTo() method from NavigationManager class anywhere to redirect to another page.


2 Answers

This behavior is because the pre-render feature. Notice that, when you are on counter page (loaded for twice), if you click on Home, only one execution is fired:

enter image description here

Summarizing:

When pre-render is enabled (by default), the prerended page's OnInitializedAsync is called for twice by design. For this reason, your redirect statement is executed for twice.

To test is I wrote this code on index OnInitializedAsync:

@page "/"
@inject IUriHelper UriHelper

<h1>Hello, world!</h1>

Welcome to your new app.

@code{

    protected async override Task OnInitializedAsync()
    {
        System.Console.WriteLine("_*   ");
        System.Console.WriteLine("_**************************");
        System.Console.WriteLine("_***** Pre render ******");
        System.Console.WriteLine("_**************************");
        System.Console.WriteLine("_   ");
        return;
    }
}

And I call the page using pre-render and from the app (without prerender). Noticed that when I force reload (prerended) the OnInitializedAsync is executed for twice:

enter image description here

Learn more about render modes.

like image 130
dani herrera Avatar answered Sep 22 '22 22:09

dani herrera


Update due to a comment by dani herrera:

The life cycle method OnInitializedAsync is called twice, but the counter @page component is called once only. This behavior is by design. The first time OnInitializedAsync is executed is when server-side Blazor app is being pre-rendering, during which time, JSInterop is not available, and thus calling UriHelper.NavigateTo("/counter"); triggers an error. The following code snippet describe how Blazor currently treats such cases:

protected override void NavigateToCore(string uri, bool forceLoad)
        {
            Log.RequestingNavigation(_logger, uri, forceLoad);

            if (_jsRuntime == null)
            {
                var absoluteUriString = ToAbsoluteUri(uri).ToString();
                throw new NavigationException(absoluteUriString);
            }

            _jsRuntime.InvokeAsync<object>(Interop.NavigateTo, uri, forceLoad);
        }

See more here. As you may realize, the counter @page component is not called, and an exception is raised.

After pre-rendering has completed, client-side SignalR establishes a connection to the server, and your app is rendered. This time (second time the method OnInitializedAsync is called) UriHelper.NavigateTo("/counter"); is properly executed, and we are happily navigated to the counter page (first time)

You may use the method OnAfterRender as a workaround, and you should verify whether a connection with the server has already been established by SignalR; that is the pre-rendering process has completed.

@page "/"
@using Microsoft.JSInterop
@inject IComponentContext ComponentContext
@inject IJSRuntime jsRuntime

<p>Navigate to the counter component.</p>

@code{

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (!ComponentContext.IsConnected) return;

         UriHelper.NavigateTo("/counter");
    }
}

Hope this helps...

like image 25
enet Avatar answered Sep 26 '22 22:09

enet