Blazor: un viaggio nello state management

di Giampaolo Tucci, in ASP.NET Core,

Quando creiamo un'applicazione Blazor anche minimamente complessa, presto o tardi ci dovremo confrontare con l'application state. Esemplificando parecchio il concetto, è possibile definire l'application state come l'insieme delle variabili utilizzate in un dato momento, unitamente al valore ad esse assegnate.

Blazor, di default, è in grado di gestire solo internal state, nel senso che questo insieme è intimamente collegato al componente dove le variabili sono state definite, e quindi quando questo viene distrutto (per esempio cambiando semplicemente pagina visualizzata) allora anche queste perdono il loro valore.

Per risolvere problemi applicativi reali spesso abbiamo la necessità di condividere variabili con diversi componenti, nonché di conservare il loro valore anche quando si cambia la pagina visualizzata. Come vedremo nel corso dell'articolo, per raggiungere questo obiettivo occorrerà adottare l'utilizzo di uno state container.

Immaginando di voler realizzare una semplice applicazione che gestisca una ToDoList, essere in grado di gestire correttamente l'application state ci permetterà di semplificarne parecchio l'implementazione.

Nel seguito presenteremo inizialmente l'applicativo senza adottare alcuno state container: solo successivamente lo completeremo adottandone uno, così da poterne coglierne i vantaggi. Infine esporremo l'utilizzo pratico di un framework adatto per gestire lo stato dell'applicazione in Blazor, e basato su Redux.

Un semplice esempio di ToDoList

Immaginiamo di voler realizzare una semplice ToDoList. Iniziamo esponendo la classe POCO delegata a contenere le informazioni relative all'attività da svolgere.

Models/ToDoItem.cs
public class ToDoItem
{
    [Required]
    public string Description { get; set; }
    public DateTime? DueDate { get; set; }
}

Dal punto di vista del markup e dei componenti Blazor, il codice sarà organizzato in modo tale da avere una pagina principale che al suo interno conterrà due componenti figli: uno che visualizzerà la lista dei ToDo e l'altro delegato all'inserimento di nuovi elementi.

Figura 1

Questi componenti dovranno accedere e condividere la stessa lista di item definita nella pagina principale, e conservata nella variabile todolist.

Pages/ToDoList.razor
@page "/todolist"

<h1>ToDo List</h1>
<CascadingValue name="todoList" Value=@todolist>
    <ToDoListComponent />
    <ToDoFormComponent/>
</CascadingValue>

@code {
    private List<ToDoItem> todolist = new List<ToDoItem>();
}

In Blazor è possibile passare valori a un componente sia usando i parametri ma anche tramite CascadingValue. Usando quest'ultimo, è possibile utilizzare l'attributo Value, contenuto appunto all'interno del tag CascadingValue, specificando quali parametri vogliamo propagare ai componenti discendenti figli (nel caso in analisi ToDoListComponent e ToDoFormComponent).

Qualsiasi componente discendente che voglia utilizzare uno di questi parametri potrà accedervi anteponendo l'attributo CascadingParameter alla sua dichiarazione. Come accade per il passaggio valori per parametri, qualsiasi variazione sul valore del parametro condiviso dalla pagina padre verrà riportato su tutti i componenti discendenti.

Nel nostro esempio abbiamo preferito usare il CascadingValue, invece che il passaggio per parametri, poiché questa soluzione ci permette di utilizzare un codice più compatto e facile da leggere. Inoltre, nel caso in futuro modificassimo l'applicazione ponendo degli ulteriori componenti come figlio di uno dei componenti sin qui utilizzati, sarebbe molto facile accedere alle variabili così condivise: infatti il valore passato per CascadingValue si propaga a tutti gli elementi figlio in una gerarchia profonda in modo arbitrario.

I componenti nel dettaglio

Spostiamoci ora ad analizzare il primo dei due componenti, che è delegato a contenere la form di inserimento di nuovi elementi nella todolist.

Components/ToDoFormComponent.razor
<div>Totale item: @todolist.Count</div>

<EditForm Model="@Newtodoitem" OnValidSubmit="@CreaTodo">
    <DataAnnotationsValidator />
    <ValidationSummary />
    
        <div class="form-field">
            <label for="descrizione">Descrizione</label>
            <InputText id="descrizione" @bind-Value=@Newtodoitem.Description />
        </div>
    
    
        <div class="form-field">
            <label for="duedate">Due Date</label>
            <InputDate id="duedate" @bind-Value=@Newtodoitem.DueDate 
              ParsingErrorMessage="Inserire un data valida" />
        </div>
    
    <button type="submit">Salva</button>
</EditForm>

@code {
    [CascadingParameter(Name = "todoList")]
    public List<ToDoItem> todolist { get; set; } = new List<ToDoItem>();

    private ToDoItem Newtodoitem = new ToDoItem();

    void CreaTodo()
    {
        todolist.Add(Newtodoitem);
        Newtodoitem = new ToDoItem();
    }
}
6 pagine in totale: 1 2 3 4 5 6
Contenuti dell'articolo

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

Top Ten Articoli

Articoli via e-mail

Iscriviti alla nostra newsletter nuoviarticoli per ricevere via e-mail le notifiche!

In primo piano

I più letti di oggi

In evidenza

Misc