Jeg har misforstått TanStack Querys cacheTime, og det har nok du også!

Marcus Haaland i Bekk oppklarer hvordan tingene egentlig henger sammen.

Etter at "alle" misforsto hva cacheTime var, har TanStack Query nå valgt å endre navnet til gcTime. 📸: Bekk
Etter at "alle" misforsto hva cacheTime var, har TanStack Query nå valgt å endre navnet til gcTime. 📸: Bekk Vis mer

TanStack Query, også kalt "React Query", forenkler datahenting i React, men med det følger en drøss med både innstillinger og begreper.

To av de mest vanlige begrepene, “staleTime” og “cacheTime”, er også de som har skapt mest forvirring.

Sistnevnte fikk et velkomment navnebytte til “gcTime” i siste versjon av TanStack Query, og etter denne posten vil du forstå hvorfor.

Svipptur innom staleTime

Før vi dykker inn i hvordan cacheTime fungerer, la oss klargjøre hva staleTime innebærer. staleTime angir hvor lang tid det tar før data markeres som gammel (stale). Når en query har gammel data, vil nye datahentinger kunne skje.

Det er viktig å forstå at selv med en staleTime på 0, betyr det ikke at det automatisk utføres et nytt nettverkskall med en gang. Nye nettverkskall utføres kun under spesifikke betingelser for å unngå konstante oppdateringer. Disse betingelsene inkluderer:

  • En ny instans av query mounter,
  • Du bytter tilbake til nettleservinduet,
  • Nettforbindelsen gjenopprettes, eller
  • Det er definert et intervall for oppdatering (refetchInterval).

staleTime angir altså hvor lang tid det tar før cachet data skal oppfattes som gammel. Hvordan relaterer staleTime seg til cacheTime?

Navnet cacheTime er misvisende

La meg teste deg med en liten quiz. Om en useQuery har staleTime på 2 minutter og cacheTime på 5 minutter, når er det cacheTime starter å telle ned?

const { data } = useQuery({
    queryKey: ['currentUser'],
    cacheTime: 5 * 60 * 1000,
    staleTime: 2 * 60 * 1000,
    queryFn: () => get<string>(url).then((response) => response.data),
});

Jeg gir deg litt tid til å tenke…

Jeg trodde først det foregikk slik:

  • query mounter og henter data
  • data markeres som gammel (stale) etter 2 minutter
  • dataen caches i 5 minutter, og slettes etterpå

Her illustrert med et bilde. Finner du noen feil?

Her illustrert at staleTime og cacheTime teller ned samtidig. Grønn er starttid, rød er sluttid.
Her illustrert at staleTime og cacheTime teller ned samtidig. Grønn er starttid, rød er sluttid. Vis mer

Om du ikke fant noen feil, har du hatt samme misoppfattelse som meg.

cacheTime er IKKE tiden cachen lagres. cacheTime har gitt så mange misforståelser at det har blitt navngitt til “gcTime” fra versjon 5. Dette er en forkortelse for “garbage-collector-time”, som bedre beskriver hva cacheTime/gcTime er: tiden før gammel cache slettes.

En annen måte å se det på, er at cacheTime ikke starter parallelt med staleTime, men heller sekvensielt etter staleTime er ferdig. Det er også verdt å merke seg at oppryddings-timeren ikke starter før query ikke er i bruk.

Her er et mer korrekt bilde:

Her illustrert at cacheTime først begynner etter staleTime er ferdig og query ikke er i bruk. Grønn er starttid, rød er sluttid.
Her illustrert at cacheTime først begynner etter staleTime er ferdig og query ikke er i bruk. Grønn er starttid, rød er sluttid. Vis mer

Praktisk eksempel på syklusen

Nå som vi har blitt litt klokere på hva forskjellen mellom staleTime og cacheTime er, la oss ta en titt på et praktisk eksempel.

La oss anta at vi bruker standardverdiene: en cacheTime på 5 min og staleTime på 0. Vi har sidene AboutPage, CompetitionPage og HomePage.

Vi besøker AboutPage, hvor en useQuery med querykey currentUser mounter.

const { data } = useQuery({
    queryKey: ['currentUser'],
    queryFn: () => get<string>(url).then((response) => response.data),
});

Siden dette er første query med nøkkel currentUser, gjør queryen et nettverkskall. Den hentede dataen blir cachet til nøkkel currentUser. Og siden staleTime er 0, vil dataene markeres som gammel med en gang.

Ved query sjekkes cache først, ellers gjøres nettverkskall. Ubrukte queries slettes etter gcTime
Ved query sjekkes cache først, ellers gjøres nettverkskall. Ubrukte queries slettes etter gcTime Vis mer

Videre, når vi navigerer til CompetitionPage, mounter vi på nytt med en querykey currentUser. Siden vi allerede har en nøkkel på currentUser, henter vi umiddelbart cachen fra tidligere. Siden dette er en ny instans av spørringen, utføres et nytt nettverkskall, men dette skjer i bakgrunnen siden det allerede er cache-data.

Når vi så besøker HomePage, som ikke bruker currentUser, vil en ny mekanisme skje. Siden staleTime for lengst er utgått og query ikke er i bruk vil cacheTime begynne å tikke ned. Etter 5 minutter vil den cachede dataen for currentUser bli slettet.

Konklusjon

Denne posten handlet om å få et fundament om hvordan staleTime og cacheTime påvirker datahenting i TanStack Query.

Det fins mye mer du kan finjustere enn jeg har dekket her, som hvordan initiell data påvirker staleTime og cache, eller hvordan du kan bruke en funksjon for å tidligere sette dataene til stale.

For videre lesing, er TanStack Query sin docs et godt sted å starte. TkDodo har også en finfin blogg om ulike bruksscenarier med TanStack Query og går mer i dybden på ulike temaer.