1
votes

L'état du compteur dans l'exemple de projet Blazor peut-il être conservé entre les changements de page?

Dans l'exemple de projet par défaut pour les projets Blazor côté serveur et WebAssembly Blazor, l'exemple Counter est réinitialisé à 0 chaque fois que vous vous déplacez entre les pages. Toutefois, sur l'exemple de projet ASP.NET React, le compteur n'est pas réinitialisé entre les commutateurs de page.

Existe-t-il un moyen pour un composant comme le compteur de conserver l'état entre la navigation de page dans Blazor (au moins pour le projet WebAssembly qui n'effectue aucun appel de serveur)?

 entrez la description de l'image ici


0 commentaires

4 Réponses :


3
votes

Il semble que ce scénario exact soit décrit dans https://docs.microsoft.com/en-us/aspnet/core/blazor/state-management?view=aspnetcore-3.0#client-side-in- the-browser

Il semble que Blazor ne le gère tout simplement pas, mais il vous suffit d'utiliser localStorage ou sessionStorage .

Utilisation du package NuGet Blazor.Extensions.Storage ( https: //github.com/BlazorExtensions/Storage ):

@page "/counter"

@inject ISessionStorage SessionStorage
@using Blazor.Extensions.Storage.Interfaces

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    protected override async Task OnInitializedAsync()
    {
        currentCount = await SessionStorage.GetItem<int>("counter");
    }

    private async void IncrementCount()
    {
        currentCount++;
        await SessionStorage.SetItem<int>("counter", currentCount);
    }
}


0 commentaires

2
votes

Je couvre cela dans mon article (fonctionne pour Blazor côté serveur ainsi que côté client (WebAssembly) Blazor): Implémentation de la gestion d'état dans Blazor

Ajoutez une classe appelée CounterState.cs en utilisant le code suivant:

@code {
    void IncrementCount()
    {
        // ** SESSION STATE
        int CurrentCount = CounterState.CurrentCount;
        CurrentCount++;
        // Set Current count on the Session State object
        CounterState.CurrentCount = CurrentCount;
    }
}

Enregistrez cette classe, en utilisant Dependency Injection, dans le Startup.cs:

<p>Current count: @CounterState.CurrentCount</p>

Ajoutez le code suivant en haut de la page de codes .razor :

<p>Current count: @currentCount</p>

Modifiez le code suivant:

@inject CounterState CounterState

En:

services.AddScoped<CounterState>();

Enfin, changez la section de code comme suit:

    public class CounterState
    {
        public int CurrentCount { get; set; }
    }


6 commentaires

Notez que Scoped est presque comme une Session mais ce counterState ne survivra pas aux reconnexions de SignalR. Assez bien pour certains scénarios, mais localState est une solution plus sûre.


@Henk Holterman - Dans la plupart des cas, vous souhaitez suivre `` l'état de la session '' et vous voudrez que toutes les valeurs non liées à la session en cours (par exemple la `` catégorie '' la plus récemment sélectionnée) `` disparaissent '' si la session a été déchargée, sinon le l'utilisateur se reconnecte et vous essayez de charger une «catégorie» qui n'est plus valide. De plus, si vous disposez d'informations «sensibles» telles que «l'identifiant de compte», vous ne souhaitez pas les stocker dans le navigateur Web local de l'utilisateur. Vous voulez le stocker en mémoire en toute sécurité et vous voulez qu'il disparaisse complètement de partout :)


Oui, mais je pense que localStore est légèrement plus «session» que le contexte SignalR.


Veuillez consulter mon implémentation d'un service générique et me faire savoir ce que vous en pensez comme une solution générale stackoverflow.com/questions/65044349/...


@Richard Davison - Ça a l'air bien :)


@MichaelWashington N'hésitez pas à déchirer ceci et à l'ajouter comme exemple sur votre site. github.com/rdavi10471a2/BlazorApp1



1
votes

Pour Blazor côté serveur, si vous souhaitez que la valeur du compteur soit conservée / mise à jour sur tous les onglets / clients, vous pouvez simplement la stocker dans une variable statique et la renvoyer si la valeur change.

 entrez la description de l'image ici

@page "/counter"

<h1>Static Counter</h1>

<p>Current static count: <span style="font-size:42px">@currentCount</span></p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    public static int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;

        StaticCount.FireUpdate();
    }

    protected override void OnInitialized()
    {
        base.OnInitialized();

        StaticCount.NewCounterValue += OnNewCounterValue;
    }

    void OnNewCounterValue(object sender, EventArgs e)
    {
        InvokeAsync(() =>
        {
            StateHasChanged();
        });
    }

    public void Dispose()
    {
        StaticCount.NewCounterValue -= OnNewCounterValue;
    }

}

@code{
    public static class StaticCount
    {
        public static event EventHandler NewCounterValue;

        public static void FireUpdate()
        {
            NewCounterValue?.Invoke(null, new EventArgs());
        }
    }
}

Vous pouvez également le faire avec un service (singleton) et même conserver la valeur dans une base de données si vous souhaitez conserver la valeur entre les redémarrages du serveur.


2 commentaires

Pouvez-vous fournir quelques détails décrivant l'approche que vous utilisez? L'OP a posé des questions sur l'assemblage côté serveur et Web (côté client), et pas seulement côté serveur. J'ai également eu l'impression que l'OP demandait simplement de se déplacer entre les applications de modèle (par exemple, la météo et le compteur) et de préserver le compteur par opposition à la préservation entre plusieurs onglets.


Pour Blazor côté serveur .. "StateHasChanged", "Cycle de vie ASP.NET Core Blazor"



0
votes

J'ai écrit une réponse à propos de la gestion de l'état de Blazor qui examine ceci ici:

https://stackoverflow.com/a/ 65609519/3850405

Ma recommandation serait un service de conteneur d'état en mémoire.

Exemple:

StateContainer.cs

XXX

Program.Main (Blazor WebAssembly):

@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;
    }
}

Startup.ConfigureServices (Blazor Server):

@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;
    }
}


0 commentaires