11
votes

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?

1

1 Answers

11
votes

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...