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 | Typ | Beschreibung |
|---|---|---|
| IfStale | default | Lä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:
- der Wert pro Ausführung auf
QueryParameters<T>, - sonst das längste passende Präfix, registriert über
DejaClient.SetDefaults, - 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#
- 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,
});
}