Blazor: Forcing Component/Page Life-cycle

938 Views Asked by At

I'm building an application using Blazor Web-assembly and I want the user to be able to load the application via a route, e.g.

http://www.someapp.com/{Page}/{Item}

If the user selects the above route it should go to {Page} and display {item}.
This works out-of-the-box; however, if the user applies the following steps:

  1. In the browser, Copy + Paste http://www.someapp.com/Inventory/1 //works
    a. SetParametersAsync (fired)
    b. OnSetParameters (fired)
  2. NEXT, change URL to http://www.someapp.com/Inventory/2 //Doesn't work
    a. SetParametersAsync (not fired)
    b. OnSetParameters (not fired)

If the {Page} is the same, the components' lifecycle doesn't kick-off even if the route parameter changed. What gives? Is there a way to force it?

Environment: VS2019
.NET CORE: v3.1

3

There are 3 best solutions below

0
On BEST ANSWER

Here's some code (based on the Counter component), copy and test it. See for yourself that both methods are executed when you change the parameter value.

Incidentally, it's OnParametersSet, not

OnSetParameters (not fired)

@page "/counter/{MyCount:int}"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;
    [Parameter]
    public int MyCount { get; set; }

    protected override void OnParametersSet()
    {
        Console.WriteLine("OnParametersSet");
    }

    public override async Task SetParametersAsync(ParameterView parameters)
    {
        Console.WriteLine("SetParametersAsync");
        await base.SetParametersAsync(parameters);
    }

    private void IncrementCount()
    {
        currentCount++;
    }
}

Note: Since Blazor reuses the Page ( currently Counter) with varying parameter; that is, it does not re-create the Page object. That is why life cycle methods such as the OnInitialized[Async) pair run only once, when the component is born.

0
On

As an appendix to @enet's answer. When I need to see what's going on in the component lifecycle, I use this block of code and markup:

@page "/lifecyclebar"

------  Your code

<div class="container m-2 px-3 p-t bg-dark text-white">
    <div class="row">
        <div class="col-3">
            Initialized: @this.InitRun
        </div>
        <div class="col-3">
            Set Params: @this.SetParamsAsync
        </div>
        <div class="col-3">
            Params Set: @this.ParamsSet
        </div>
        <div class="col-3">
            Rendered: @this.Rendered
        </div>
    </div>
</div>

@code {

---- your code

    private int SetParamsAsync = 0;
    private int InitRun = 0;
    private int ParamsSet = 0;
    private int Rendered = 1;

    //  add to existing method if you have one
    protected override Task OnInitializedAsync()
    {
        InitRun++;
        return base.OnInitializedAsync();
    }

    //  add to existing method if you have one
    protected override Task OnParametersSetAsync()
    {
        this.ParamsSet++;
        return base.OnParametersSetAsync();
    }

    //  add to existing method if you have one
    public override Task SetParametersAsync(ParameterView parameters)
    {
        this.SetParamsAsync++;
        return base.SetParametersAsync(parameters);
    }

    //  add to existing method if you have one
    protected override bool ShouldRender()
    {
        Rendered++;
        return true;
    }
}
0
On

I'll try to remove this question but the solution to my issue was the caching policy. After a hard-reload then the page behaves as expected. Thank you to those who took their time to help address this issue.

It did help having code "that works" (that which was posted) and trying that on my system to help locate the source of this time sink.