Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blazor page not rerendering after parameter updated

Tags:

c#

blazor

I started out with the new ASP.NET core web app and the blazor client-side template (3.0.0-preview4-19216-03).

To add state to the existing Counter.razor page, I added the following class:

public class GlobalCounter
{
    private int _count;
    public int Count
    {
        get => _count;
        set
        {
            if (_count == value) return;

            _count = value;
            CounterChanged.Invoke(this, new CounterChangedEventArgs(_count));
        }
    }

    public GlobalCounter(int initialCount = 0)
    {
        _count = initialCount;
    }

    public event EventHandler<CounterChangedEventArgs> CounterChanged;
}

public class CounterChangedEventArgs : EventArgs
{
    public int Count { get; }
    public CounterChangedEventArgs(int count)
    {
        Count = count;
    }
}

Within Startup.cs added following to the ConfigureServices method:

public void ConfigureServices(IServiceCollection services)
{
    var counter = new GlobalCounter();
    services.AddSingleton(counter);
}

Next I added the singleton to be injected into the Counter.razor page:

@inject GlobalCounter _counter;

Also added the following code to the @functions of the page:

protected override async Task OnInitAsync()
{
    currentCount = _counter.Count;
    _counter.CounterChanged += CounterChanged;
    await Task.CompletedTask;
}

void CounterChanged(object sender, CounterChangedEventArgs args)
{
    currentCount = args.Count;
}

void IncrementCount()
{
   _counter.Count++;
}

Until now it works as expected, leaving the page or reloading will keep the old count.

Next, I adjusted the index.razor to inject the counter and display the count clicked.

@page "/"
@inject GlobalCounter _counter;

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

You pressed the counter @totalCount times.

@functions {
    private int totalCount = 0;

    protected override async Task OnInitAsync()
    {
        totalCount = _counter.Count;
        _counter.CounterChanged += CounterChanged;
        await Task.CompletedTask;
    }

    void CounterChanged(object sender, CounterChangedEventArgs args)
    {
        totalCount = args.Count;
    }
}

This also works as expected. Pressing the "click me" button on the Counter page and navigating back to the index page, will show the correct count.

Here comes my issue, as soon as I add the <Counter /> page as a component within the index.razor, pressing the "click me" button will update the count within the component but not the text displayed on the index page.

blazor render issue demonstration

Is there an explicit call needed to rerender dependent components or some specific binding between pages?

like image 549
Raul Avatar asked Apr 23 '19 10:04

Raul


People also ask

How do you refresh a page in Blazor?

A page is reloaded/refreshed automatically at a specified interval using “NavigationManager” in OnAfterRender() method. Here the NavigateTo(“url”, forceLoad: true) method, is used to force load the browser based on the URI.

How do you force Rerender Blazor?

To force a component to rerender, use the “StateHasChanged” method in Blazor, to notify that the state has been changed and requires re-rendering.

How do you pass parameters to Blazor page?

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.

What does @inject do in Blazor?

Use the @inject directive to inject the service into components. @inject has two parameters (type and name). Type represents the service type and name represents the service instance name.


1 Answers

Try this in index.razor:

void CounterChanged(object sender, CounterChangedEventArgs args)
{
    totalCount = args.Count;

    StateHasChanged();
}

You've got to tell Blazor that the state of the component has changed and that she should rerender.

Incidentally, the value in the Counter component is automatically updated because the StateHasChanged method is called by Blazor after the "Click me" button's click event is triggered. StateHasChanged method is automatically called after events of any event type are raised...

like image 196
enet Avatar answered Oct 20 '22 08:10

enet