C# Academy · leksjon

Tilstandshåndtering i Blazor

Administrer delt tilstand med singleton-tjenester, Fluxor eller kaskaderende AppState for å holde brukergrensesnittet konsistent på tvers av komponenter.

Leksjon 4 av 412 trinn

Tilstandshåndtering i Blazor er en gratis leksjon i C# Academy på CoddyKit. Dette er leksjon 4 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i C# Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i C# Academy inneholder totalt 4 leksjoner.

Utfordringer med tilstandsbehandling i Blazor

Etter hvert som Blazor-apper vokser, blir det komplekst å håndtere tilstand som må deles mellom mange urelaterte komponenter. Enkel prop-drilling fungerer ikke lenger; De trenger et sentralisert, reaktivt tilstandslager.

Enkel tilstand med en scoped-tjeneste

Den enkleste formen for tilstandsbehandling i Blazor er en scoped-tjeneste som inneholder tilstanden og eksponerer en hendelse som komponenter kan abonnere på ved endringer.

public class CartState
{
    private readonly List<CartItem> _items = new();
    public IReadOnlyList<CartItem> Items => _items;
    public int Count => _items.Sum(i => i.Quantity);

    public event Action? OnChanged;

    public void Add(Product p)
    {
        var existing = _items.FirstOrDefault(i => i.ProductId == p.Id);
        if (existing is not null) existing.Quantity++;
        else _items.Add(new CartItem { ProductId = p.Id, Name = p.Name, Price = p.Price });
        OnChanged?.Invoke();
    }
}

Abonnere på tilstandsendringer

Komponenter abonnerer på OnChanged-hendelsen i tilstandstjenesten og kaller StateHasChanged for å gjengi komponenten på nytt. Husk å avslutte abonnementet i Dispose.

@inject CartState Cart
@implements IDisposable

<p>Cart: @Cart.Count items</p>

@code {
    protected override void OnInitialized()
    {
        Cart.OnChanged += OnCartChanged;
    }

    private void OnCartChanged()
    {
        InvokeAsync(StateHasChanged);
    }

    public void Dispose() =>
        Cart.OnChanged -= OnCartChanged;
}

CascadingValue som tilstandsbeholder

Pakk inn rotlayouten i en CascadingValue med tilstandstjenesten. Alle etterkommere kan få tilgang til den uten eksplisitt prop-drilling.

@* MainLayout.razor *@
@inject CartState Cart

<CascadingValue Value="Cart">
    @Body
</CascadingValue>

@* Any nested component: *@
@code {
    [CascadingParameter]
    public CartState Cart { get; set; } = default!;

    private void Buy(Product p) => Cart.Add(p);
}

Fluxor: Flux-mønsteret for Blazor

Fluxor bringer en Redux-lignende enveis dataflyt til Blazor: State → Component → Action → Reducer → State. Dette passer godt for komplekse applikasjoner.

// dotnet add package Fluxor.Blazor.Web

// State record
[FeatureState]
public record CounterState(int Count = 0);

// Actions
public record IncrementAction(int Amount = 1);

// Reducers
public static class CounterReducers
{
    [ReducerMethod]
    public static CounterState Reduce(CounterState state, IncrementAction action)
        => state with { Count = state.Count + action.Amount };
}

// Registration:
builder.Services.AddFluxor(opt =>
    opt.ScanAssemblies(typeof(Program).Assembly));

Bruke Fluxor i en komponent

Injiser IState<T> for å lese tilstanden og IDispatcher for å sende handlinger. InheritsFrom<FluxorComponent> (eller mixin-en) abonnerer automatisk på tilstandsendringer.

@inherits FluxorComponent
@inject IState<CounterState> CounterState
@inject IDispatcher Dispatcher

<p>Count: @CounterState.Value.Count</p>
<button @onclick="Increment">+1</button>
<button @onclick="() => Dispatcher.Dispatch(new IncrementAction(5))">+5</button>

@code {
    private void Increment()
        => Dispatcher.Dispatch(new IncrementAction(1));
}

Persistens med localStorage

Bevar tilstanden mellom sideoppdateringer ved å bruke nettleserens localStorage via JavaScript-interoperabilitet. Gjenopprett den når appen starter.

@inject IJSRuntime JS

@code {
    private async Task SaveStateAsync()
    {
        var json = JsonSerializer.Serialize(_state);
        await JS.InvokeVoidAsync("localStorage.setItem", "appState", json);
    }

    protected override async Task OnInitializedAsync()
    {
        var json = await JS.InvokeAsync<string?>("localStorage.getItem", "appState");
        if (json is not null)
            _state = JsonSerializer.Deserialize<AppState>(json) ?? new();
    }

    private AppState _state = new();
}

Blazored.LocalStorage-pakken

Blazored.LocalStorage-pakken tilbyr et rent, typesikkert API over nettleserens localStorage uten at De må skrive JS interop-kall manuelt.

// dotnet add package Blazored.LocalStorage
builder.Services.AddBlazoredLocalStorage();

@inject ILocalStorageService LocalStorage

@code {
    protected override async Task OnInitializedAsync()
    {
        _cart = await LocalStorage.GetItemAsync<List<CartItem>>("cart") ?? new();
    }

    private async Task SaveCartAsync()
    {
        await LocalStorage.SetItemAsync("cart", _cart);
    }

    private List<CartItem> _cart = new();
}

URL-tilstand med NavigationManager

Bruk spørringsparametere for å lagre tilstand som skal overleve en sideoppdatering og kunne brukes i bokmerker. Les og skriv dem via NavigationManager og URI-byggeren.

@inject NavigationManager Nav
@page "/products"

@code {
    [SupplyParameterFromQuery] public string? Search { get; set; }
    [SupplyParameterFromQuery] public int Page { get; set; } = 1;

    private void UpdateSearch(string s)
    {
        Nav.NavigateTo(
            Nav.GetUriWithQueryParameters(
                new Dictionary<string, object?>
                {
                    [nameof(Search)] = s,
                    [nameof(Page)]   = 1
                }));
    }
}

I praksis: Tilstand for handlekurv

Et komplett mønster: en scoped CartState-tjeneste med hendelser, lagret i localStorage ved endringer og gjenopprettet ved innlasting.

public class CartState
{
    private readonly ILocalStorageService _storage;
    private List<CartItem> _items = new();
    public event Action? OnChanged;

    public CartState(ILocalStorageService storage) => _storage = storage;

    public async Task InitAsync()
    {
        _items = await _storage.GetItemAsync<List<CartItem>>("cart") ?? new();
    }

    public async Task AddAsync(Product p)
    {
        var item = _items.FirstOrDefault(i => i.ProductId == p.Id);
        if (item is not null) item.Quantity++;
        else _items.Add(new CartItem { ProductId = p.Id, Name = p.Name });
        await _storage.SetItemAsync("cart", _items);
        OnChanged?.Invoke();
    }
}

Kjapp kontroll

Hvilken tilnærming til tilstandsbehandling passer best for en enkel Blazor-app med begrenset delt tilstand?

Oppsummering: Tilstandsbehandling i Blazor

Viktigste punkter:

  • Scoped-tjeneste + Action-hendelse: den enkleste delte tilstanden, og god for de fleste apper
  • CascadingValue rundt roten gir tilgang i hele appen uten prop-drilling
  • Fluxor: Redux-lignende enveis flyt for kompleks tilstandslogikk
  • Bevar tilstanden i localStorage med IJSRuntime eller Blazored.LocalStorage
  • URL-tilstand (SupplyParameterFromQuery) for UI-tilstand som kan bokmerkes og deles
  • Avslutt alltid abonnementer på hendelser i Dispose for å hindre minnelekkasjer
Gratis å komme i gang

Lær deg C# med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
93
Leksjoner
346

Ofte stilte spørsmål

Er leksjonen «Tilstandshåndtering i Blazor» gratis?

Ja – hele teksten i «Tilstandshåndtering i Blazor» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av C# Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i C# Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Tilstandshåndtering i Blazor»?

Administrer delt tilstand med singleton-tjenester, Fluxor eller kaskaderende AppState for å holde brukergrensesnittet konsistent på tvers av komponenter. Du øver på C# Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med C# Academy?

Ingen tidligere erfaring er nødvendig. C# Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.

Hvor lang tid tar leksjonen «Tilstandshåndtering i Blazor»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne C# Academy-leksjonen?

Ja. Alle C# Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Blazor-komponentmodellen
  2. Databinding og hendelseshåndtering
  3. Kommunikasjon mellom komponenter og DI
  4. Tilstandshåndtering i Blazor
← Tilbake til C# Academy