# ref, DOM e stato: chi possiede cosa

useRef conserva un valore senza ri-renderizzare, lo stato ri-renderizza il componente: la scelta dipende da chi deve vedere il cambiamento.

> Pagina: https://ui.eneawork.it/blog/react-ref-dom-vs-state
> Markdown: https://ui.eneawork.it/blog/react-ref-dom-vs-state.md

*2026-11-01*

Lo stato possiede ciò che disegna il render, la ref possiede ciò che serve al comportamento: un nodo del DOM, un timer, l'ultimo valore visto. Cambiare una ref non ridisegna nulla.

Il catalogo EneUI conta 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie, misurati da /api/stats il 1 novembre 2026. La cifra viene da una query all'endpoint, non da una stima: conta i record pubblicati, non la qualità dei componenti.

## La regola in una riga

Se il valore compare nel markup, è stato. Se lo leggi solo dentro un effetto o un gestore di eventi, è una ref. Nel dubbio chiediti chi deve accorgersi del cambiamento: se la risposta è l'utente, serve stato.

## Il caso eseguibile

import { useEffect, useRef, useState } from "react"; export function CampoRicerca() { const input = useRef(null); const tentativi = useRef(0); const [testo, setTesto] = useState(""); useEffect(() => { input.current?.focus(); }, []); function invia(e) { e.preventDefault(); tentativi.current += 1; } return ( setTesto(e.target.value)} /> Cerca ); }

Il campo è controllato dallo stato, il nodo e il contatore vivono nelle ref. Il contatore non compare a schermo: se dovesse comparire, diventerebbe stato e il componente si ridisegnerebbe a ogni invio.

## Ref e server component

Le ref richiedono un client component: puntano a un nodo del browser, che sul server non esiste. Un componente con useRef e senza direttiva di client viene rifiutato in build, non a runtime.

## Misurare invece di indovinare

Per leggere larghezza o posizione usa una callback ref con ResizeObserver, non una ref letta durante il render. Il valore misurato è un dato del browser, quindi appartiene a un effetto, non al corpo del componente.

## Record vivi nel catalogo

La categoria input raccoglie i campi del catalogo, con un input di chat che gestisce focus e altezza; un esempio di blocco è input-10.

## La limitazione

Una ref non notifica nessuno: due componenti non possono sincronizzarsi su di essa senza uno stato che li svegli. Inoltre la mutazione durante il render è invisibile a React, che in concurrent rendering può scartare il calcolo e lasciare la scrittura al suo posto.

## Dove continuare

Il confine fra client e server è in un hook importato in un server component; il doppio avvio degli effect è in useEffect due volte in sviluppo; come si legge la documentazione è in leggere la documentazione React. Il confronto con Vue è in Vue 3 vs React.

## FAQ

### Perché cambiare una ref non aggiorna la pagina?

Perché React non osserva le ref. Solo lo stato e le props avviano un render, quindi un valore in ref cambia senza che l'interfaccia lo sappia.

### Posso usare una ref al posto dello stato per un contatore?

Sì se il contatore non compare mai a schermo e serve solo alla logica. Appena deve essere visibile o cambiare il markup, serve stato.

### A cosa serve ref su un elemento DOM?

A chiamare metodi che React non espone, come focus, select o scrollIntoView. Per leggere valori di un campo controllato basta lo stato.

### Una ref sopravvive ai ri-render?

Sì, l'oggetto è lo stesso per tutta la vita del componente. Cambia solo quando il componente viene smontato e ricreato, per esempio con una key diversa.

### Perché la ref è null al primo render?

Perché React la riempie dopo aver creato il nodo. Va letta in un effetto o in un gestore, non nel corpo del componente.
