The AppState pattern is one of the simplest State Management patterns to implement with Blazor WebAssembly.
To start implementing the pattern, declare a class that describes the collection of fields that represents the state of a page, a form, or a model.
Here are some basic example state objects:
public class Counter{public int Counter { get; set; }}public class RegistrationForm{public Guid FormId { get; set; }public string EmailAddress { get; set; }public string GivenName { get; set; }public string Surname { get; set; }public string JobTitle { get; set; }}public class TimesheetEntry{public int Id { get; set; }public int ClientId { get; set; }public string ClientName { get; set; }public int ProjectId { get; set; }public string ProjectName { get; set; }public decimal HourlyRate { get; set; }public DateTime StartTime { get; set; }public DateTime EndTime { get; set; }public string Notes { get; set; }}public class Timesheet{public int Id { get; set; }public string UserName { get; set; }public TimesheetEntry[] Entries { get; set; }}
Typically, these state objects would be hydrated from user input or a request to the backend API. In order for us to use this state object, we first need to register it as an injectable service (in Program.cs):
builder.Services.AddScoped<Counter>();builder.Services.AddScoped<RegistrationForm>();builder.Services.AddScoped<Timesheet>();
Once registered, we can use the @inject directive to inject the object into a page or component:
@page "/counterWithState"@* Inject our CounterState and use it in the view and/or code section *@@inject Counter _state<PageTitle>Counter</PageTitle>@* we can reference the state object in the Razor markup *@<p>Current count: @_state.Count</p>@* Note: Due to user interaction, the page will refresh and show updated state value, even though we have not called StateHasChanged *@<button type="button" @onclick="IncrementCount">Click me</button><button type="button" @onclick="Reset">Reset</button>@code {private void IncrementCount(){// we can modify the state object in the @code section++_state.Count;}private void Reset(){_state.Count = 0;}}
Alternatively if we are using code-behind (separate .razor and .razor.cs files), then we can use the [Inject] attribute to inject the object as a parameter for the code-behind class.
Note: Constructor based injection is not supported for Blazor code-behind. Only Parameter based injection is supported.
public partial class Counter : ComponentBase{[Inject]public Counter State { get; set; }private void IncrementCount(){++_state.Count;}private void Reset(){_state.Count = 0;}}
StateHasChanged() manually when we modify the state@code (aka ViewModel) section