In-memory state container service

Nested components typically bind data using chained bind as described in ASP.NET Core Blazor data binding. Nested and un-nested components can share access to data using a registered in-memory state container. A custom state container class can use an assignable Action to notify components in different parts of the app of state changes. In the following example:

  • A pair of components uses a state container to track a property.
  • The components of the example are nested, but nesting isn’t required for this approach to work.
  • Session is lost if user refresh the page.

StateContainer.cs

public class StateContainer
{
    public string Property { get; set; } = "Initial value from StateContainer";

    public event Action OnChange;

    public void SetProperty(string value)
    {
        Property = value;
        NotifyStateChanged();
    }

    private void NotifyStateChanged() => OnChange?.Invoke();
}

In Program.Main (Blazor WebAssembly):C#Copy

builder.Services.AddSingleton<StateContainer>();

In Startup.ConfigureServices (Blazor Server):C#Copy

services.AddSingleton<StateContainer>();

Pages/Component1.razor

@page "/Component1"
@inject StateContainer StateContainer
@implements IDisposable

<h1>Component 1</h1>

<p>Component 1 Property: <b>@StateContainer.Property</b></p>

<p>
    <button @onclick="ChangePropertyValue">Change Property from Component 1</button>
</p>

<Component2 />

@code {
    protected override void OnInitialized()
    {
        StateContainer.OnChange += StateHasChanged;
    }

    private void ChangePropertyValue()
    {
        StateContainer.SetProperty($"New value set in Component 1 {DateTime.Now}");
    }

    public void Dispose()
    {
        StateContainer.OnChange -= StateHasChanged;
    }
}

Shared/Component2.razor

@inject StateContainer StateContainer
@implements IDisposable

<h2>Component 2</h2>

<p>Component 2 Property: <b>@StateContainer.Property</b></p>

<p>
    <button @onclick="ChangePropertyValue">Change Property from Component 2</button>
</p>

@code {
    protected override void OnInitialized()
    {
        StateContainer.OnChange += StateHasChanged;
    }

    private void ChangePropertyValue()
    {
        StateContainer.SetProperty($"New value set in Component 2 {DateTime.Now}");
    }

    public void Dispose()
    {
        StateContainer.OnChange -= StateHasChanged;
    }

Sources:

https://docs.microsoft.com/en-us/aspnet/core/blazor/state-management?view=aspnetcore-5.0&pivots=webassembly

Last modified: November 25, 2020

Author

Comments

Write a Reply or Comment