<ForrigeUke uke="32" år="2025" />
En del av:
ForrigeUke<ForrigeUke /> er en artikkelserie som oppsummerer hva som skjedde i frontend-verden i uken som var.
TanStack DB har kommet i beta! Dette er et lag som kan gå oppå din eksisterende bruk av TanStack Query. Men idet jeg trodde TanStack Query var svaret på alt, hvorfor skal vi bry oss om enda et verktøy?
Svaret på dette tok meg ned et kaninhull.
Dette var uka for holdninger og lettelser — og 596 ting som skjedde i frontendverdenen!
«<ForrigeUke /> er en artikkelserie som oppsummerer hva som skjedde i frontend-verden i uka som var.»

Hvorfor holder ikke TanStack Query?
Query løser de vanskeligste problemene ved servertilstand, som caching, synkronisering og optimistiske oppdateringer. Men TanStack Query behandler data som isolerte cache-instanser. Selv om data i virkeligheten kan henge sammen, er de uavhengige sett fra TanStack Query utifra den definerte query-nøkkelen. DB skal gi dette relasjonelle laget, hvor du kan kombinere og filtrere data, uten en hel masse re-rendringer.
Hvordan få til relasjoner med TanStack DB?
Med TanStack DB kommer nye begreper. Ikke mindre kompliserende, er det at du kan bruke TanStack DB oppå flere verktøy. Heldigvis har Mathews og Willis fra DB-teamet skrevet en fin intro til dette verktøyet.
I TanStack DB er “collection” et av de viktige begrepene. Det er her du definerer den lokale lagringsplassen, som du spør og skriver til.
Når du bruker TanStack DB oppå TanStack Query, skjer koblingen via @tanstack/query-db-collection. Det er denne pakken som lar deg definere collections som henter og oppdaterer data med TanStack Query under panseret. Du får altså fortsatt caching, refetching og alle Query-fordelene — men nå med DBs collections, live queries og relasjoner på toppen.
Når du bruker TanStack DB med TanStack Query, vil du i collection definere CRUD. For lesing mater du inn queryFn og queryKey (i stedet for å kalle useQuery direkte i komponenten). For skriving bruker du heller ikke useMutation, men definerer oppdateringsfunksjonene onUpdate (update), onInsert (create) og onDelete (delete) i collection.
Her er et eksempel hvor vi henter data fra endepunktet “api/todos”. Vi definerer queryFn og queryKey for å hente data, men definerer også en oppdatering med onUpdate:
import { createCollection } from '@tanstack/react-db'
// 👇 Importerer queryCollectionOptions for tanstack query
import { queryCollectionOptions } from '@tanstack/query-db-collection'
// 👇 I collection definerer vi hvordan vi laster inn data (queryFn) og
// hvordan data blir endret (blant annet onUpdate)
const todoCollection = createCollection(
queryCollectionOptions({
// 👇 queryKey og queryFn er likt som med TanStack Query
queryKey: ['todos'],
queryFn: async () => {
const response = await fetch('/api/todos')
return response.json()
},
// 👇 Unik nøkkel på objektet som kan brukes til joining av datakilder
getKey: (item) => item.id,
// 👇 Vi definerer også hva som skal skje ved endringer
onUpdate: async ({ transaction }) => {
const { original, modified } = transaction.mutations[0]
await fetch(`/api/todos/${original.id}`, {
method: 'PUT',
body: JSON.stringify(modified),
})
},
})
)
Det er i collection vi definerer hvordan dataene blir hentet og skal bli oppdatert, så dette vil variere utifra om vi bruker TanStack DB med TanStack Query og REST (som over) eller annet verktøy (som vi kommer tilbake til).
Når vi kommer ned til bruken av dataene i komponentene, vil ting se mer likt ut på tvers av verktøy. For å lese av data i komponenten, bruker vi useLiveQuery. I denne funksjonen kan vi filtrere data og formatere dataene som vi vil:
import { eq, useLiveQuery } from '@tanstack/react-db'
function Todos() {
// 👇 live-query oppdateres automatisk når data endres
const { data: todos } = useLiveQuery((q) =>
q.from({ todo: todoCollection })
// 👇 I datahentingen kan vi kombinere og filtrere på dataene
.where(({ todo }) => eq(todo.completed, false))
.orderBy(({ todo }) => todo.createdAt, 'desc')
)
// ...
}
Om vi ville, kunne vi også ha samlet ulike collections i samme data-objekt i useLiveQuery:
const { data: rows } = useLiveQuery((q) =>
q
.from({ t: todoCollection })
// 👇 Vi joiner flere collections
.innerJoin({ u: userCollection }, ({ t, u }) => eq(t.userId, u.id))
.select(({ t, u }) => ({
id: t.id,
title: t.title,
completed: t.completed,
assignee: u.name,
}))
)
Det er denne kombineringen og formateringen på tvers av datakilder som er er et av salgspunktene for TanStack DB. Med joins, filtrering og selekterte felter i live queries manipulerer du data enklere — og fordi spørringene oppdateres kun med endringene (et prinsipp kjent som differential dataflow, istedenfor å kjøre hele query på nytt), får du samtidig en merkbar ytelsesgevinst.
Men det er en ting til ved TanStack DB. Og denne funksjonaliteten er så sentral, at verktøyet hadde funksjonaliteten i navnet sitt. TanStack DB starta livet som “TanStack Optimistic”. DB skal nemlig ha mye enklere syntaks for optimistisk oppdatering.
Igjen bruker vi collection-objektet, hvor vi har definert oppdaterings-funksjonen:
function Todos() {
// ...
const toggleTodo = (todo) => {
// 👇 Umiddelbart optimistisk oppdatering, så syncing til serveren
todoCollection.update(todo.id, (draft) => {
draft.completed = !draft.completed
})
}
Se hvor enkelt den optimistiske oppdateringen er satt opp!
På få linjer har vi likevel tilgang på ganske komplisert funksjonalitet, og med ytelsesforbedringene som nevnt over. Med DB trenger du altså ingen manuell lagring av forrige tilstand og rulle tilbake ved feil, som jeg tidligere har vist med TanStack Query.
Lokalt først
TanStack DB passer godt inn i “local-first”-bevegelsen. Local-first var visst en trend i 2024 (uten at jeg la merke til det av den grunn). Local-first handler om å prioritere lagring og prosessering på data i brukerens enhet (enn å lene seg på en sentral server), og gi kontroll til brukeren. Selskapet Electric prøvde å støtte dette med synkmotoren (sync engine) ElectricSQL, men som CEO i Electric, James Arthur, sier i foredraget på Local-first conf, så er TanStack det mest populære valget for server-state, og vil bruke TanStack DB som en gateway drug til ElectricSQL.
Hvorfor bruke en synkmotor?
Et av poengene med DB er å ha et felles grensesnitt for å hente og oppdatere data. Det fungerer fint å bruke det med TanStack Query og REST. Men om du ønsker å kunne støtte appen din uten nett, og også få appen til å kjennes umiddelbar, kan en synkmotor være løsningen.
En synkmotor er et lag mellom databasen og klienten. Det skal ikke bare sørge for rask kommunikasjon, men også lokal lagring og toveis-synkronisering.
Her er ElectricSQL et populært valg. Det kobles til Postgres-databasen og kopierer utvalgte data (shapes) til en lokal database i klienten. Når noe endrer seg i databasen, strømmer ElectricSQL endringene til klienten. Det skjer også andre vei: når du endrer noe lokalt, skyves endringene tilbake til serveren. TanStack DBs live queries vil så sørge for at hele grensesnittet er oppdatert.
Om du skal gi en følelse av sanntid med TanStack Query, kan du legge til et refetchInterval i query-en. Men med synkmotorer kan du enklere sette det opp og oppdateringer blir dyttet automatisk. Når du ikke trenger å hvile på et intervall blir sanntidsfunksjonaliteten mer effektiv.
Samtidig ønsker ikke TanStack DB å pushe synkmotorer på deg, hvert fall ikke overalt. Forskjellen i syntaks er bare en annerledes collection- import (og annerledes implementeringslogikk i selve collection):
import { queryCollectionOptions } from '@tanstack/query-db-collection';
import { electricCollectionOptions } from '@tanstack/electric-db-collection';
Syntaksen for collection.update og dataene fra liveQuery vil fortsatt være lik. Du kan ha TanStack Query- collections for de vanlige tingene, og eventuelt legge inn Electric SQL-collections (eller andre synkmotorer, også Firebase- støtte er på vei) der det passer inn.
En ny type statehåndtering?
TanStack DB introduserer en ny type statehåndtering, sier Jack Herrington. Vi har allerede native React-tilstand med useState og useReducer, enveis tilstand med Redux og Zustand, toveis med MobX og atom-basert med Jotai. TanStack DB er noe eget: en live klientside database hvor du jobber mot collections og leser live queries som oppdaterer grensesnittet fortløpende.
Så når kan dette være nyttig?
Det kan være relevant når du ønsker hyppige endringer, sanntid- oppdatering, offline støtte og når flere kilder må kombineres. Det kan derimot være overkill ved enkel visning, få data eller sjelden oppdatering.
Nå er verktøyet fortsatt i beta, så det blir spennende når flere begynner å ta det i bruk og flere bruksscenarier blir klarere.
👋 Det var alt for denne uka. Snakkes neste uke!
Del kunnskapen
Har du en kollega som også hadde dratt nytte av denne artikkelen?
Skrevet av
Mer fra Fag i Bekk
Nå er du ved veis ende. Gå til forsiden hvis du vil ha mer faglig påfyll.
Til forsiden