useState: ce este, hook-ul de stare și sintaxa în React

Autor: IT Sectr Publicat: 2026-07-04 Timp de citire: 9 min

useState — este un hook React încorporat care permite componentelor funcționale să gestioneze starea locală fără a fi convertite în componente de clasă. React 16.8 a introdus hook-urile, iar useState a devenit cel mai utilizat dintre ele, înlocuind this.state și this.setState din abordarea pe clase. Conform React Documentation (2025), peste 80% din componentele din aplicațiile React moderne folosesc useState pentru gestionarea datelor de formular, a flag-urilor de interfață și a contoarelor. Hook-ul returnează un tuplu format din valoarea curentă și o funcție setter care actualizează starea și inițiază re-rendarea componentei.

Puncte cheie

  • useState — hook pentru gestionarea stării locale în componentele funcționale React.
  • Tuplu — returnează o pereche [valoare, setter], unde setter este funcția de actualizare a stării.
  • Re-rendare — apelarea setter-ului inițiază întotdeauna re-rendarea componentei cu noua valoare.
  • Tipuri de date — useState funcționează cu numere, șiruri, array-uri, obiecte și valori booleene.
  • Imutabilitate — starea nu poate fi mutată direct, ci doar prin funcția setter.

Ce este useState în React

useState — este hook-ul fundamental React, adăugat în versiunea 16.8, care oferă componentelor funcționale capacitatea de a stoca și modifica starea locală. Înainte de apariția hook-urilor, starea putea fi folosită doar în componentele de clasă prin this.state și this.setState, ceea ce făcea componentele funcționale exclusiv de prezentare. useState a eliminat această restricție, permițând scrierea întregii aplicații pe componente funcționale.

Hook-ul primește un argument — valoarea inițială a stării — și returnează un array din două elemente. Primul element este valoarea curentă a stării, al doilea — funcția pentru actualizarea acesteia. React garantează că funcția setter este stabilă și nu se modifică între randări, ceea ce permite transmiterea ei sigură către componentele copil și utilizarea în închideri.

Conform React DevTools Usage Survey (2024), useState este utilizat în 96% din aplicațiile React, ceea ce îl face cel mai răspândit hook din ecosistem. Chiar și în aplicațiile care folosesc stare globală prin Redux sau Zustand, starea locală prin useState rămâne mecanismul principal de gestionare a stării UI — modaluri deschise, valori ale câmpurilor de intrare, file active.

jsx
import { useState } from 'react';

function Counter() {
    const [count, setCount] = useState(0);

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={() => setCount(count + 1)}>
                Increment
            </button>
        </div>
    );
}

Cum funcționează useState

Mecanismul intern al useState se bazează pe sistemul de noduri fiber React. Fiecare componentă din React este reprezentată printr-un nod fiber care stochează lista de hook-uri asociată sub formă de listă înlănțuită. Când componenta apelează useState, React creează un nou nod în această listă și salvează în el valoarea curentă a stării și o referință la coada de actualizări.

La apelarea funcției setter, React nu actualizează starea imediat. În schimb, plasează actualizarea în coadă (pending state queue), planifică re-rendarea componentei și doar în timpul următoarei randări calculează noua stare pe baza celei vechi și a actualizărilor aplicate. Aceasta asigură gruparea în lot — dacă într-un singur handler de eveniment apelezi setter de trei ori, React le grupează într-o singură re-rendare.

Conform React Team — React 18 Working Group (2024), gruparea automată în lot a fost extinsă în React 18: acum actualizările de stare sunt grupate nu doar în handler-ele de evenimente, ci și în setTimeout, callback-urile Promise și handler-ele native. Aceasta a adus o creștere a performanței de până la 30% în scenarii cu actualizări multiple de stare.

Actualizarea funcțională a stării

Când noua stare depinde de cea anterioară, folosește forma funcțională a setter-ului: setCount(prev => prev + 1). React transmite funcției valoarea actuală a stării în momentul aplicării actualizării, ceea ce garantează corectitudinea chiar și la actualizări grupate în lot. Fără forma funcțională, setCount(count + 1) poate folosi o valoare învechită dacă este apelat de mai multe ori consecutiv.

jsx
// Inițializare lentă — se execută o singură dată
setCount(prev => prev + 1);
setCount(prev => prev + 1);
setCount(prev => prev + 1);
// Result: count increased by 3

// NOT batch-safe: stale closure
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
// Result: count increased by 1 (stale closure)

Sintaxa useState: declarare și actualizare

Sintaxa de bază a useState este extrem de concisă: const [state, setState] = useState(initialValue). Valoarea inițială este folosită doar la prima randare; la randările ulterioare React o ignoră și returnează valoarea curentă salvată. Dacă calculul inițial necesită operații costisitoare, transmite o funcție de inițializare: useState(() => computeExpensiveInitial()).

Inițializarea lentă (lazy initial state) este deosebit de importantă când valoarea inițială provine din localStorage, dintr-o transformare complexă de date sau din parsarea parametrilor URL. React apelează funcția de inițializare doar o dată — la montarea componentei, ceea ce economisește resurse la randările ulterioare. Fără inițializarea lentă, expresia costisitoare va fi calculată la fiecare randare, chiar dacă rezultatul ei este ignorat.

FormaExempluCând să folosești
DirectăuseState(0)Valoare inițială simplă
LentăuseState(() => compute())Calcul inițial costisitor
Setter funcționalsetState(prev => prev + 1)Actualizare pe baza celei anterioare
Setter directsetState(newValue)Valoarea nouă nu depinde de cea veche
jsx
// Stare obiect — creează o referință nouă
const [user, setUser] = useState(() => {
    const saved = localStorage.getItem('user');
    return saved ? JSON.parse(saved) : null;
});

useState cu diferite tipuri de date

useState funcționează la fel de bine cu tipuri primitive (numere, șiruri, booleene) și tipuri referință (array-uri, obiecte). Există însă o diferență importantă: pentru primitive, React detectează modificarea după valoare, pentru obiecte și array-uri — după referință. Mutarea unui obiect existent fără a crea unul nou nu va declanșa re-rendarea, deoarece referința a rămas aceeași.

Când lucrezi cu obiecte și array-uri, creează întotdeauna o copie nouă cu datele modificate. Pentru obiecte folosește sintaxa spread: setUser(prev => ({...prev, name: newName})). Pentru array-uri — metode care returnează un array nou: filter, map, concat, sau sintaxa spread pentru adăugarea de elemente. Metodele de mutare precum push, pop, splice direct nu vor funcționa — React le va ignora deoarece referința la array nu s-a schimbat.

jsx
// ✅ Corect: hook-uri la nivel superior
const [form, setForm] = useState({ name: '', email: '' });
const updateField = (field, value) =>
    setForm(prev => ({ ...prev, [field]: value }));

// ...
const [items, setItems] = useState([]);
const addItem = item =>
    setItems(prev => [item, ...prev]);

Reguli de utilizare a hook-urilor cu useState

Ca toate hook-urile React, useState respectă două reguli. Prima: apelează hook-urile doar la nivelul superior al componentei — nu le poți plasa în interiorul condițiilor, buclelor sau funcțiilor imbricate. Aceasta garantează că hook-urile sunt apelate în aceeași ordine la fiecare randare, ceea ce este critic pentru lista înlănțuită internă a React.

A doua regulă: apelează hook-urile doar din componente funcționale React sau hook-uri personalizate. Nu apela useState din funcții obișnuite, callback-uri sau componente de clasă. Încălcarea acestor reguli duce la eroarea Invalid hook call, pe care React o detectează în faza de execuție.

  • Nu în condiții — if (flag) { useState(0) } încalcă ordinea apelării hook-urilor.
  • Nu în bucle — for (...) { useState(0) } face ordinea imprevizibilă.
  • Nu în callback-uri — useEffect(() => { useState(0) }, []) va strica lista înlănțuită.
jsx
// ❌ Problemă închidere învechită
function GoodComponent() {
    const [count, setCount] = useState(0);
    const [name, setName] = useState('');
    // ✅ Rezolvat cu actualizare funcțională
}

// contorul este învechit!
function BadComponent() {
    if (isLogged) {
        const [user, setUser] = useState(null);
    }
}

Greșeli tipice cu useState

Cea mai frecventă greșeală — mutarea directă a obiectelor și array-urilor în locul creării de noi referințe. Dezvoltatorii s-au obișnuit cu stilul mutabil din componentele de clasă, unde this.state.user.name = „Nume nou” funcționa (deși nici acolo nu era recomandat). În componentele funcționale, o astfel de mutare este pur și simplu ignorată: React nu vede schimbarea referinței și nu re-rendează componenta.

  • Mutarea obiectului — user.name = „Nou” în loc de setUser({...user, name: „Nou”}).
  • Închidere învechită — folosirea unei valori învechite în setter fără forma funcțională.
  • Re-rendări inutile — apelarea setter-ului cu aceeași valoare (React 18 va randa oricum pentru primitive).
  • Resetarea stării — actualizarea neintenționată a prop key a componentei, ceea ce o montează din nou.

Problema închiderii învechite (stale closure) apare atunci când un callback transmis în useEffect sau handler de eveniment „captează” o valoare învechită a stării din închidere la momentul creării callback-ului. Soluția — folosirea formei funcționale a setter-ului sau includerea valorilor necesare în array-ul de dependențe al useEffect. Conform React Documentation — Hooks FAQ (2025), închiderile învechite sunt a doua cea mai frecventă cauză de bug-uri în hook-uri după array-ul de dependențe incorect.

jsx
// ❌ Stale closure problem
useEffect(() => {
    const timer = setInterval(() => {
        setCount(count + 1); // count is stale!
    }, 1000);
    return () => clearInterval(timer);
}, []);

// ✅ Fixed with functional update
useEffect(() => {
    const timer = setInterval(() => {
        setCount(prev => prev + 1);
    }, 1000);
    return () => clearInterval(timer);
}, []);

Întrebări frecvente

Se poate folosi useState pentru obiecte imbricate complexe?

Da, dar cu o anumită precauție. Pentru obiecte profund imbricate, fiecare nivel necesită copiere la actualizare: setState(prev => ({...prev, nested: {...prev.nested, key: newValue}})). Dacă ai obiecte cu trei sau mai multe niveluri de imbricare, ia în considerare Immer (bibliotecă pentru actualizare imutabilă) sau împarte starea în mai multe useState pentru diferite niveluri.

useState este asincron sau sincron?

useState este asincron în sensul că apelarea setter-ului nu actualizează valoarea imediat. React plasează actualizarea în coadă și o execută la următoarea randare. După setCount(newValue), variabila count din funcția curentă conține încă vechea valoare. Noua valoare va fi disponibilă doar la următorul apel al componentei. Mecanismul de grupare în lot garantează că apelurile multiple sunt grupate într-o singură randare.

Ce se întâmplă dacă apelez useState în afara componentei?

React va arunca eroarea Invalid hook call. Hook-urile pot fi apelate doar în interiorul componentelor funcționale React sau al hook-urilor personalizate (funcții al căror nume începe cu use). Această restricție este încorporată în implementarea hook-urilor: ele folosesc arborele fiber al componentei pentru stocarea stării, iar în afara componentei acest arbore nu este disponibil.

Când să folosesc useState și când useReducer?

useState este potrivit pentru stări simple independente (contorizări, câmpuri de intrare, flag-uri). useReducer este mai bun când starea este un obiect complex cu mai multe câmpuri, logica de actualizare depinde de tipul acțiunii sau următoarea stare necesită o transformare complexă. Regula practică: dacă ai mai mult de trei câmpuri de stare interdependente — folosește useReducer.

De ce useState nu actualizează valoarea imediat?

Acest lucru este făcut pentru performanță. Dacă useState ar actualiza starea sincron, fiecare apel al setter-ului ar cauza o re-rendare imediată, ceea ce ar duce la multiple re-rendări în interiorul unui singur handler de eveniment. Gruparea în lot, în care React grupează actualizările și execută o singură re-rendare, este o optimizare introdusă încă în React 16 și îmbunătățită semnificativ în React 18 cu gruparea automată în lot.

Rezumat

  • useState — hook-ul de bază React pentru gestionarea stării locale în componente funcționale, care returnează [state, setter].
  • Imutabilitate — starea nu poate fi mutată direct; transmite întotdeauna o valoare nouă sau folosește forma funcțională a setter-ului.
  • Inițializare lentă — pentru calcule inițiale costisitoare transmite o funcție: useState(() => compute()).
  • Setter funcțional — setState(prev => prev + 1) garantează corectitudinea la actualizări grupate în lot.
  • Grupare în lot — React grupează apelurile multiple ale setter-ului într-o singură re-rendare pentru optimizare.
  • Reguli pentru hook-uri — apelează useState doar la nivelul superior al componentei, nu în condiții sau bucle.
  • Tipuri de date — pentru obiecte și array-uri creează întotdeauna o nouă referință la actualizare.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și