useRef — ce este, hook-ul referințelor și lucrul cu DOM în React

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

useRef — este un hook React care creează un obiect ref mutabil cu proprietatea .current, păstrat între redările componentului. Spre deosebire de useState, modificarea .current nu provoacă re-rendare, ceea ce face useRef ideal pentru stocarea referințelor DOM, timerelor și oricăror valori care trebuie să supraviețuiască redărilor fără a redesena UI. Conform React Documentation (2025), obiectul ref este creat o dată pe durata de viață a componentului și nu se schimbă între redări, garantând stabilitatea referinței.

Principalele puncte

  • useRef — hook pentru crearea unui obiect ref mutabil cu câmpul .current.
  • Fără re-rendare — modificarea .current nu provoacă redesenarea componentului.
  • Referințe DOM — se transmite în prop-ul ref al elementului pentru acces direct la nodul DOM.
  • Stocarea valorilor — potrivit pentru timere, valori anterioare și orice date între redări.
  • Referință stabilă — obiectul ref nu se schimbă între redări, spre deosebire de închideri.

Ce este useRef în React

useRef — este un hook adăugat în React 16.8, care returnează un obiect ref mutabil cu o singură proprietate .current. Valoarea inițială este atribuită .current la montarea componentului. Diferența principală față de o variabilă obișnuită — obiectul ref supraviețuiește re-rendărilor: la re-rendare, React nu recrează ref-ul, ci returnează același obiect.

Implementarea internă a useRef folosește același mecanism ca useState și useEffect — o listă înlănțuită de hook-uri pe nodul fiber. Totuși, spre deosebire de useState, React nu urmărește modificările obiectului ref, nu pune actualizări în coadă și nu planifică re-rendarea. Acest lucru face useRef un hook extrem de ușor, care nu afectează performanța chiar și la modificări frecvente.

Conform React Team — Hooks FAQ (2025), useRef este în esență o «cutie» care stochează o valoare. Zahăr sintactic: const ref = useRef(initialValue) este echivalent cu const ref = { current: initialValue } cu diferența că React garantează că obiectul ref va fi același la fiecare redare. Nimic magic — doar o referință stabilă gestionată de React.

jsx
import { useRef } from 'react';

function Component() {
    const countRef = useRef(0);
    // countRef.current = 0 inițial
    // countRef.current = 5 după mutare
    // Nu are loc re-rendarea!
}

Accesul la elementele DOM prin useRef

Cel mai comun scenariu de utilizare a useRef — obținerea accesului direct la elementul DOM. React atribuie elementRef.current referința la nodul DOM după montarea componentului. Acest lucru este necesar pentru focusarea input-ului, măsurarea dimensiunilor elementului, integrarea cu bibliotecile de animații și bibliotecile care nu folosesc redarea React.

React gestionează automat referințele ref la DOM: la montare atribuie nodul DOM real, la demontare îl resetează (setează null). Acest lucru garantează că în .current există întotdeauna o valoare actualizată și previne scurgerile de memorie prin referințe «atârnate» către elemente șterse. Nu este necesară nicio curățare manuală.

jsx
function AutoFocusInput() {
    const inputRef = useRef(null);

    useEffect(() => {
        // Focus input după montarea componentului
        inputRef.current?.focus();
    }, []);

    return <input ref={inputRef} type="text" />;
}

Conform React — Refs and DOM documentation (2025), nu folosi ref pentru operații declarative — deschiderea/închiderea modalurilor, gestionarea vizibilității. În aceste scopuri există state și props. Ref-urile sunt destinate operațiilor imperative care nu pot fi exprimate declarativ: focus, selectare text, integrare cu biblioteci terțe.

Stocarea valorilor mutabile fără re-rendări

Al doilea scenariu ca importanță — stocarea valorilor arbitrare care trebuie păstrate între redări, dar a căror modificare nu ar trebui să provoace re-rendarea. Exemple tipice: identificatori de timere (setInterval/setTimeout), flaguri pentru anularea cererilor, valori anterioare ale props-urilor pentru comparație și orice date care nu afectează ieșirea UI.

Acest lucru este util în special în useEffect: useRef stochează identificatorul timer-ului, iar cleanup-ul îl șterge. Dacă timerId este stocat în useState, fiecare apel setTimerId ar provoca o re-rendare inutilă care nu este necesară nici pentru logică, nici pentru UI. useRef rezolvă această problemă fără overhead și fără redesenări inutile.

jsx
function Timer() {
    const intervalRef = useRef(null);

    const start = () => {
        intervalRef.current = setInterval(() => {
            console.log('tictac');
        }, 1000);
    };

    const stop = () => {
        clearInterval(intervalRef.current);
    };

    useEffect(() => stop, []);

    return <><button onClick={start}>Start</button><button onClick={stop}>Stop</button></>;
}

useRef vs useState: când să folosești ce

Dilema principală — alegerea între useRef și useState — se rezolvă cu o întrebare: «Este necesară re-rendarea la modificarea valorii?». Dacă da — useState. Dacă nu — useRef. useState stochează starea care afectează ieșirea componentului; useRef stochează datele necesare pentru logica internă, dar care nu afectează UI.

În practică, dezvoltatorii folosesc adesea useRef pentru a stoca callback-uri, pentru a evita problemele cu închiderile. De exemplu, dacă useEffect se abonează la un eveniment și în interiorul callback-ului este nevoie de state-ul actual — stochează callback-ul în useRef. La fiecare redare actualizează ref.current cu noua funcție, iar efectul va apela întotdeauna callback-ul proaspăt fără reabonare.

CriteriuuseRefuseState
Re-rendareNu provoacă la modificareProvoacă la fiecare setState
MutareDirectă: ref.current = valuePrin setter: setState(value)
Folosire în JSXNu se folosește (fără efect)Se folosește în ieșirea componentului
ExempluTimere, referințe DOM, valori anterioareDate de formular, stare UI, flaguri

Există un anti-pattern: folosirea useRef pentru a stoca date care sunt necesare în JSX, dar a căror modificare nu ar trebui să provoace re-rendare. Acest lucru duce la desincronizare — UI afișează date vechi, deși ref.current este deja nou. Dacă valoarea este afișată în UI — folosește useState. Dacă este folosită doar în logica internă — useRef.

useRef în combinație cu useEffect

Combinația useRef + useEffect — un pattern standard pentru urmărirea valorilor anterioare ale props-urilor. Stochează valoarea anterioară în ref, compar-o cu cea curentă în useEffect și ia o decizie pe baza diferenței. Acest lucru este util în special la animații, când trebuie să știi ce valoare a fost înainte de modificare.

jsx
function PriceDisplay({ price }) {
    const prevPriceRef = useRef(price);

    useEffect(() => {
        const prevPrice = prevPriceRef.current;
        if (price > prevPrice) {
            animateUp();
        } else if (price < prevPrice) {
            animateDown();
        }
        prevPriceRef.current = price;
    }, [price]);

    return <span>${price}</span>;
}

Conform React Documentation — Hooks FAQ (2025), acest pattern se numește «previous value pattern». Funcționează deoarece useRef păstrează valoarea între redări, iar useEffect se execută după confirmarea modificărilor. Mai întâi DOM-ul este actualizat cu noul price, apoi useEffect compară cu cel anterior (care este încă în ref) și actualizează ref.current la valoarea curentă.

Greșeli tipice cu useRef

Cea mai frecventă greșeală — citirea ref.current în faza de redare pentru a calcula JSX-ul. Deoarece modificarea ref.current nu provoacă re-rendare, componentul poate folosi o valoare învechită. Dacă valoarea .current participă la ieșirea UI — folosește useState. Dacă trebuie să sincronizezi ref și state, folosește useEffect pentru a actualiza state-ul din ref.

  • Ref în JSX — citirea ref.current în funcția de redare duce la desincronizarea UI și a datelor.
  • Ref ca dependență useEffect — ref.current nu ar trebui să fie în array-ul de dependențe; React nu urmărește modificările sale.
  • Verificare null uitată — la demontare ref.current devine null; verifică înainte de acces.
  • Stocarea funcțiilor în ref — actualizează ref.current la fiecare redare dacă folosești pattern-ul cu callback proaspăt.
jsx
// ❌ Nu citi ref.current în timpul redării pentru afișare
function BadComponent() {
    const valRef = useRef(0);
    return <p>{valRef.current}</p>; // NU se va actualiza la mutare
}

// ✅ Folosește state pentru afișare, ref pentru logică
function GoodComponent() {
    const [val, setVal] = useState(0);
    const valRef = useRef(0);
    return <p>{val}</p>;
}

O altă greșeală comună — folosirea useRef ca unic mod de stocare a stării în component, atunci când datele afectează totuși UI. Dezvoltatorii aleg useRef pentru a evita re-rendările «inutile», dar în final obțin un UI care nu se actualizează. Abordarea corectă: folosește useState pentru datele UI și useRef doar pentru valorile auxiliare care nu participă la redare.

Întrebări frecvente

Se poate folosi useRef pentru a stoca starea anterioară?

Da, acesta este un pattern comun — previous state pattern. Creează un ref și actualizează-l în useEffect la fiecare modificare a valorii urmărite. În momentul dintre redare și efect, ref.current conține valoarea anterioară care poate fi comparată cu cea curentă. Acest lucru nu necesită re-rendări suplimentare și funcționează cu orice tip de date.

De ce ref.current este null la prima redare?

React atribuie ref.current valoarea nodului DOM doar după ce elementul este redat și adăugat în DOM-ul real. În timpul primei redări, componentul nu este încă montat, deci ref.current este egal cu valoarea inițială (null). Accesul la DOM prin ref.current este posibil doar în useEffect sau în handler-ele de evenimente care sunt apelate după montare.

Care este diferența dintre useRef și createRef?

createRef creează un nou obiect ref la fiecare redare — trebuie folosit doar în componentele de clasă. useRef creează ref-ul o dată și returnează același obiect la toate redările ulterioare. În componentele funcționale folosește exclusiv useRef; createRef va duce la pierderea valorii la re-rendare, deoarece obiectul va fi recreat.

Se poate transmite useRef prin props?

Da, obiectul ref poate fi transmis ca un prop obișnuit: <Child inputRef={inputRef} />. Componentul copil îl folosește prin inputRef.current. Totuși, pentru a transmite ref direct la elementul DOM al componentului copil, folosește forwardRef — un HOC care permite trecerea ref-ului prin props. Fără forwardRef, ref-ul nu va fi legat automat la elementul DOM din interiorul componentului copil.

Cum se măsoară dimensiunea unui element cu useRef?

Legă ref-ul de element, apoi în useEffect citește ref.current.getBoundingClientRect() sau ref.current.offsetWidth / offsetHeight. Pentru urmărirea reactivă a modificărilor de dimensiune, folosește ResizeObserver în interiorul useEffect: creează un observer, abonează-te la modificări și actualizează state-ul cu noile dimensiuni. Nu uita să dezactivezi observer-ul în cleanup.

Rezumat

  • useRef — hook pentru crearea unui obiect ref mutabil, păstrat între redări fără a provoca re-rendare.
  • Acces DOM — prop-ul ref se transmite elementului pentru acces direct la nodul DOM; disponibil după montare.
  • Stocarea datelor — timere, callback-uri, flaguri și orice valori care nu afectează UI se stochează în ref.
  • useRef vs useState — alege useState dacă modificarea trebuie să redeseneze UI; useRef — dacă nu.
  • Previous value pattern — stochează valoarea anterioară în ref, actualizează în useEffect pentru comparație.
  • Ref în JSX — nu citi ref.current în faza de redare; acest lucru duce la desincronizarea UI și a datelor.
  • forwardRef — folosește pentru a transmite ref prin props către componentul copil.

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