webroad.online
  1. 1Web
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Unelte
  8. 8React
  9. 9State management
  10. 10Next.js
  11. 11Formulare
  12. 12Date și backend
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Animații
  16. 16Testare
  17. 17Arhitectură
React · Lecția 7 din 7

Server state și TanStack Query

De ce datele de pe server nu sunt useState, query keys, staleTime și invalidare.

Actualizat

Ce este server state

Server state = date care trăiesc pe server (în baza de date, într-un API), iar tu ai în browser doar o copie: useri, produse, comenzi, comentarii. Opusul e client state — date care există doar în UI: un modal deschis, textul dintr-un input, tema.

Diferența nu e academică — cele două au probleme complet diferite:

Client state Server state
Exemple tema, modal deschis, pas dintr-un wizard useri, produse, comenzi
Proprietar tu (UI-ul) serverul — tu ai o copie
Sincron da nu — vine prin rețea
Se poate învechi nu oricând (alt user l-a modificat)
Probleme unde îl ții loading, erori, cache, deduplicare, refetch, invalidare, paginare
Unelte useState, URL, Zustand Server Components, TanStack Query, SWR

Greșeala clasică: date de server în useState + useEffect. Ajungi să reimplementezi — prost — cache, loading, retry, deduplicare.

Varianta 1: Server Components (Next.js)

Aduci datele pe server și randezi direct HTML-ul. Nu există loading state pe client, nu există cache de sincronizat în browser.

export default async function Page() {
  const posts = await getPosts()        // cache-uit cu 'use cache' + cacheTag('posts')
  return <PostList posts={posts} />
}

Mutație → Server Action → updateTag('posts') → pagina se re-randează cu date proaspete.

Varianta 2: TanStack Query (pe client)

O librărie care gestionează server state în browser: cache, refetch, deduplicare, retry, paginare, mutații.

const { data, isPending, error } = useQuery({
  queryKey: ['posts', { page }],                       // identitatea datelor în cache
  queryFn: () => api(`/api/posts?page=${page}`),
  staleTime: 60_000,                                   // 1 min proaspete → fără refetch
})

const queryClient = useQueryClient()
const createPost = useMutation({
  mutationFn: (post: NewPost) => api('/api/posts', { method: 'POST', body: JSON.stringify(post) }),
  onSuccess: () => queryClient.invalidateQueries({ queryKey: ['posts'] }),
})

Conceptele cheie

Concept Ce înseamnă
queryKey array care identifică datele; tot ce influențează rezultatul intră în cheie (page, filtre)
staleTime cât timp datele sunt „proaspete”; implicit 0 = mereu considerate vechi
gcTime cât rămân în cache după ce nu le mai folosește nimeni (implicit 5 min)
invalidateQueries marchează ca vechi → refetch pentru ce e pe ecran; potrivire pe prefix
deduplicare 3 componente cer ['user', 1] → un singur request
refetch automat la focus pe fereastră, la reconectare, la montare (dacă e stale)

Optimistic update

Afișezi rezultatul înainte de răspunsul serverului, ca UI-ul să pară instant; dacă eșuează, revii.

Unde Cum
React 19 / Server Actions useOptimistic
TanStack Query onMutate (actualizezi cache-ul) + onError (rollback)

Cum alegi

Situație Alegere
pagini Next care afișează date (blog, catalog, profil) Server Components
mutații din formulare în Next Server Actions + updateTag
UI foarte interactiv cu date de server: dashboard, infinite scroll, polling, filtre live TanStack Query (poți face prefetch pe server)
SPA fără server propriu TanStack Query
state pur de UI useState / URL / Zustand

Pe scurt

  • Server state = copie locală a unor date de pe server; se poate învechi oricând.
  • Nu-l pune în useState + useEffect.
  • Next: Server Components + Server Actions; pe client: TanStack Query cu queryKey, staleTime, invalidare.

Surse oficiale

Exerciții

Ți-a fost utilă pagina?

Un click — fără cont.