sulmar / nobleprog-merrid-blazor

Przykłady ze szkolenia Blazor 8
0 stars 0 forks source link

Dlaczego metoda OnInitializedAsync wywoływana jest dwa razy? #1

Open sulmar opened 3 weeks ago

sulmar commented 3 weeks ago

Dlaczego mając następujący kod metoda OnInitializedAsync wywoływana jest dwa razy?

@page "/customers"
@inject ICustomerRepository Repository
@rendermode InteractiveServer

<h3>List</h3>

@if (customers is null)
{
    <p>Loading customers...</p>
}
else
{
    <ul>
        @foreach (var customer in customers)
        {
            <li>@customer.Name @customer.Id</li>
        }
    </ul>
}

@code {

    private IEnumerable<Customer> customers;

    protected override async Task OnInitializedAsync()
    {

        await Task.Delay(10_000);

        customers = await Repository.GetAllAsync();

    }

}
sulmar commented 3 weeks ago

W Blazor Server metoda OnInitializedAsync może być wywoływana dwa razy z powodu procesu renderowania komponentu, szczególnie przy użyciu określonych trybów renderowania lub procesów rehydratacji. Oto najczęstsze przyczyny podwójnego wywoływania OnInitializedAsync w Twoim kodzie:

  1. Tryb renderowania i pre-renderowanie: Używasz @rendermode InteractiveServer, który ustawia komponent, aby wspierał interaktywne działanie Blazor Server po początkowej fazie wstępnego renderowania na serwerze. Gdy określony jest InteractiveServer:
    • Blazor najpierw wstępnie renderuje komponent na serwerze.
    • Następnie, po nawiązaniu połączenia z serwerem, ponownie renderuje komponent interaktywnie. W cyklu życia Blazora OnInitializedAsync jest wywoływany zarówno podczas wstępnego renderowania, jak i podczas renderowania interaktywnego, co skutkuje dwoma wywołaniami. Takie działanie jest zamierzone, ponieważ Blazor najpierw renderuje zawartość wstępnie (dla lepszego SEO lub szybszego pierwszego ładowania), a następnie ładuje interaktywną zawartość.
  2. Rozwiązanie: Zapobieganie podwójnym wywołaniom: Aby uniknąć dwukrotnego wykonywania logiki (np. pobierania danych z serwera), można dodać flagę, aby sprawdzić, czy dane zostały już załadowane.

Oto jak zmodyfikować kod:

@page "/customers"
@inject ICustomerRepository Repository
@rendermode InteractiveServer

<h3>Lista</h3>

@if (customers is null)
{
    <p>Ładowanie klientów...</p>
}
else
{
    <ul>
        @foreach (var customer in customers)
        {
            <li>@customer.Name @customer.Id</li>
        }
    </ul>
}

@code {

    private IEnumerable<Customer> customers;
    private bool isInitialized = false;

    protected override async Task OnInitializedAsync()
    {
        if (!isInitialized)
        {
            await Task.Delay(10_000);
            customers = await Repository.GetAllAsync();
            isInitialized = true;
        }
    }

}

W ten sposób OnInitializedAsync pobiera dane tylko raz, niezależnie od tego, ile razy komponent zostanie ponownie wyrenderowany.