Refetching & Aktualität

Die Stale-Time entscheidet, wann gecachte Daten revalidiert werden müssen; Refetch() ist der explizite Override, der immer lädt.

Stale-Time#

Nach einem erfolgreichen Fetch sind Daten für die Dauer von StaleTime frisch. Ein Execute mit Key, das frische Daten findet, liefert den Cache und lädt nicht. Der Bibliotheks-Default ist TimeSpan.Zero — gecachte Daten rendern sofort, werden beim nächsten Mount aber immer im Hintergrund revalidiert. „Gecacht“ heißt erst dann „kein Request“, wenn du die Stale-Time erhöhst (diese Seite verwendet 10 Sekunden).

RefetchOnMount#

Steuert, ob ein Execute mit Key, das gecachte Daten findet, zusätzlich neu lädt:

Wert TypBeschreibung
IfStale defaultLädt nur dann im Hintergrund neu, wenn die Daten älter als die Stale-Time sind.
Always Lädt immer im Hintergrund neu, auch solange die Daten frisch sind.
Never Liefert den Cache und lädt beim Mount nie neu. Invalidierung lädt weiterhin neu.

Ein Key ohne gecachte Daten lädt immer, unabhängig von dieser Einstellung — und ein invalidierter Eintrag lädt selbst unter Never neu: Invalidierung ist eine explizite Anforderung, keine Mount-Policy.

Manuelles Refetch()#

Refetch() führt das letzte Execute mit erzwungenem frischem Fetch erneut aus — die Stale-Prüfung, RefetchOnMount und Enabled werden allesamt umgangen. Auf dem gecachten Pfad aktualisiert das Ergebnis den gemeinsamen Eintrag, jede Komponente auf dem Key rendert also neu; einem parallelen Fetch auf demselben Key wird beigetreten, statt ihn zu duplizieren. Vor dem ersten Execute (oder nach dem Disposen) tut es nichts.

<button @onclick="() => _todos.Refetch()">Refresh</button>

// with one-shot overrides:
await _todos.Refetch(new RefetchParameters<List<Todo>>
{
    StaleTime = TimeSpan.FromSeconds(30),   // how soon the fresh result goes stale again
    OnSettled = _ => _lastRefreshed = DateTimeOffset.Now,
});

Einmalige Overrides#

RefetchParameters<T> kann Callbacks, den Token und die Stale-/Cache-Zeiten überschreiben — nur für diesen einen Aufruf. Key und Fetch-Funktion kommen immer vom letzten Execute: Sie zu ändern ist eine neue Query, kein Refetch. Ein späteres Refetch() ohne Parameter bleibt von früheren Overrides unberührt.

Vorrang der Defaults#

Überall, wo Stale-Time, Cache-Time oder RefetchOnMount gesetzt werden können, gilt die Kette:

  1. der Wert pro Ausführung auf QueryParameters<T>,
  2. sonst das längste passende Präfix, registriert über DejaClient.SetDefaults,
  3. sonst der globale DejaOptions-Default.
// Per-prefix defaults: reference data rarely changes, keep it fresh for an hour.
client.SetDefaults(QueryKey.Of("countries"), new QueryDefaults
{
    StaleTime = TimeSpan.FromHours(1),
    RefetchOnMount = RefetchOnMount.Never,
});

Live-Demo#

Refetch und IsReFetching
List query IsLoading IsReFetching IsError IsCachedData IsStale ReFetchCount: 1UpdatedAt: 20:33:39
  • delectus aut autem
  • quis ut nam facilis et officia qui
  • fugiat veniam minus

A manual Refetch() always fetches — staleness, RefetchOnMount and Enabled are bypassed. The existing list stays on screen while IsReFetching is on: no loading flash. The override variant keeps the fresh result “not stale” for 30 seconds instead of the site default of 10 — for this call only.

@inherits DejaComponentBase
@inject JsonPlaceholderApi Api

<div class="demo-toolbar">
    <button class="demo-button primary" @onclick="() => _todos.Refetch()">Refetch()</button>
    <button class="demo-button" @onclick="RefetchWithOverride">Refetch with StaleTime = 30 s</button>
</div>

<StateInspector Query="_todos" Label="List query"/>

@if (_todos.Data is { } todos)
{
    <ul class="demo-list">
        @foreach (var todo in todos)
        {
            <li>@todo.Title</li>
        }
    </ul>
}
else if (_todos.IsLoading)
{
    <p class="demo-note">Loading…</p>
}

@if (_lastRefetchAt is { } at)
{
    <p class="demo-note">Last manual refetch settled at @at.ToString("HH:mm:ss").</p>
}

<p class="demo-note">
    A manual <code>Refetch()</code> always fetches — staleness, <code>RefetchOnMount</code> and
    <code>Enabled</code> are bypassed. The existing list stays on screen while
    <code>IsReFetching</code> is on: no loading flash. The override variant keeps the fresh result
    “not stale” for 30 seconds instead of the site default of 10 — for this call only.
</p>

@code {
    private readonly Query<IReadOnlyList<TodoDto>> _todos = new();
    private DateTimeOffset? _lastRefetchAt;

    protected override Task OnInitializedAsync()
        => _todos.Execute(DocsKeys.TodoList(3), token => Api.GetTodosAsync(3, token), p => p.OnError = _ => { });

    private Task RefetchWithOverride() => _todos.Refetch(new RefetchParameters<IReadOnlyList<TodoDto>>
    {
        StaleTime = TimeSpan.FromSeconds(30),
        OnSettled = _ => _lastRefetchAt = DateTimeOffset.Now,
    });
}