Axium7
Axium7

Reputation: 189

Injecting a custom service into a hierarchy of components

I have a singleton service that I am passing as a parameter into a Index.razor. Index.razor is re-rendered when I clear the counter. When I pass the same service to Component1 and click the Increase Count button the page is not re-rendered. If I reload the page I can see the Counter increase.

Thank you for your assistance.

PS. I am not able to format the MyService class properly. I tried several times. My apologies. I am new to Stack Overflow.

Service

namespace Injection.Pages

{ public class MyService { public int Counter { get; set; } public void increaseCount() { Counter = Counter + 1;

    }

    public void clearCounter()
    {
        Counter = 0;
    }

}

}

Index
@page "/" @inject MyService myService

<h3>Injection</h3>

<button @onclick="clearCounter">Clear Count</button>
<br />
<br />

@myService.Counter

<Component1 myService="myService" />

@code
{
    private void clearCounter ()
    {
        myService.clearCounter();
        StateHasChanged();
    }
}

Component

    <h3>Component1</h3>

<button @onclick="increaseCount">Increase Count</button>

@code {
    [Parameter]
    public MyService myService { get; set; }

    private void increaseCount()
    {
        myService.increaseCount();
        StateHasChanged();
    }
}

Upvotes: 0

Views: 100

Answers (1)

Fengzhi Zhou
Fengzhi Zhou

Reputation: 1667

In summary, though you have set the state, the change is not notified between components. Here is a sample.

Service

public class MyService
{
    public int Counter { get; set; }
    public Action OnChange { get; set; }

    public void increaseCount()
    {
        Counter += 1;
        NotifyStateChanged();
    }

    public void clearCounter()
    {
        Counter = 0;
        NotifyStateChanged();
    }

    private void NotifyStateChanged()
    {
        var task = Task.Run(() => OnChange?.Invoke());
    }

}

Home

@page "/"
@using BlazorApp71.Components.Pages
@inject MyService myService

<h3>Injection</h3>

<button @onclick="clearCounter">Clear Count</button>
<br />
<br />

@myService.Counter

<Component1 myService="myService" />

@code
{
    protected override void OnInitialized()
    {
        myService.OnChange += async () => await InvokeAsync(StateHasChanged);
    }

    private void clearCounter()
    {
        myService.clearCounter();
    }

    public void Dispose()
    {
        myService.OnChange -= async () => await InvokeAsync(StateHasChanged);
    }
}

Component

<h3>Component1</h3>

<button @onclick="increaseCount">Increase Count</button>

@code {
    [Parameter]
    public MyService myService { get; set; }

    protected override void OnInitialized()
    {
        myService.OnChange += async () => await InvokeAsync(StateHasChanged);
    }

    private void increaseCount()
    {
        myService.increaseCount();
    }

    public void Dispose()
    {
        myService.OnChange += async () => await InvokeAsync(StateHasChanged);
    }
}

There are some other approaches to communicate between components https://chrissainty.com/3-ways-to-communicate-between-components-in-blazor/ . You can refer to this for more information.

Upvotes: 1

Related Questions