Nota bene

Questa pagina è stata tradotta automaticamente e supervisionata da un maintainer. Un’ulteriore revisione da parte della community sarebbe comunque utile. Migliora questa traduzione.

useRef è un Hook React che ti permette di referenziare un valore non necessario per la renderizzazione.

const ref = useRef(initialValue)

Reference

useRef(initialValue)

Chiama useRef al top level del tuo componente per dichiarare un ref.

import { useRef } from 'react';

function MyComponent() {
const intervalRef = useRef(0);
const inputRef = useRef(null);
// ...

Vedi altri esempi sotto.

Parameters

  • initialValue: Il valore con cui vuoi inizializzare la proprietà current dell’oggetto ref. Può essere un valore di qualsiasi tipo. Questo argomento viene ignorato dopo la renderizzazione iniziale.

Returns

useRef restituisce un oggetto con una singola proprietà:

  • current: Inizialmente è impostato al valore initialValue che hai passato. Puoi impostarlo su qualcos’altro in seguito. Se passi l’oggetto ref a React come attributo ref di un nodo JSX, React imposterà la sua proprietà current.

Nelle renderizzazioni successive, useRef restituirà lo stesso oggetto.

Caveats

  • Puoi mutare la proprietà ref.current. A differenza dello state, è mutabile. Tuttavia, se contiene un oggetto usato per la renderizzazione (ad esempio, una porzione del tuo state), non dovresti mutare quell’oggetto.
  • Quando cambi la proprietà ref.current, React non ri-renderizza il tuo componente. React non è a conoscenza di quando la modifichi perché un ref è un normale oggetto JavaScript.
  • Non scrivere né leggere ref.current durante la renderizzazione, tranne per l’inizializzazione. Questo rende imprevedibile il comportamento del tuo componente.
  • In Strict Mode, React chiamerà la funzione del tuo componente due volte per aiutarti a trovare impurità accidentali. Questo è un comportamento solo in development e non influisce sulla production. Ogni oggetto ref verrà creato due volte, ma una delle versioni verrà scartata. Se la funzione del tuo componente è pura (come dovrebbe essere), non dovrebbe influire sul comportamento.

Usage

Referenziare un valore con un ref

Chiama useRef al top level del tuo componente per dichiarare uno o più ref.

import { useRef } from 'react';

function Stopwatch() {
const intervalRef = useRef(0);
// ...

useRef restituisce un oggetto ref con una singola proprietà current inizialmente impostata al valore iniziale che hai fornito.

Nelle renderizzazioni successive, useRef restituirà lo stesso oggetto. Puoi cambiare la sua proprietà current per conservare informazioni e leggerle in seguito. Potrebbe ricordarti lo state, ma c’è una differenza importante.

Modificare un ref non avvia una ri-renderizzazione. Questo significa che i ref sono perfetti per conservare informazioni che non influenzano l’output visivo del tuo componente. Ad esempio, se devi conservare un ID di intervallo e recuperarlo in seguito, puoi metterlo in un ref. Per aggiornare il valore all’interno del ref, devi modificare manualmente la sua proprietà current:

function handleStartClick() {
const intervalId = setInterval(() => {
// ...
}, 1000);
intervalRef.current = intervalId;
}

In seguito, puoi leggere quell’ID di intervallo dal ref per poter cancellare l’intervallo:

function handleStopClick() {
const intervalId = intervalRef.current;
clearInterval(intervalId);
}

Usando un ref, ti assicuri che:

  • Puoi conservare informazioni tra le ri-renderizzazioni (a differenza delle variabili normali, che si azzerano a ogni renderizzazione).
  • Modificarlo non avvia una ri-renderizzazione (a differenza delle variabili di state, che avviano una ri-renderizzazione).
  • Le informazioni sono locali a ogni copia del tuo componente (a differenza delle variabili esterne, che sono condivise).

Modificare un ref non avvia una ri-renderizzazione, quindi i ref non sono appropriati per conservare informazioni che vuoi mostrare sullo schermo. Usa lo state per quello. Leggi di più su scegliere tra useRef e useState.

Esempi di referenziare un valore con useRef

Esempio 1 di 2:
Contatore di click

Questo componente usa un ref per tenere traccia di quante volte è stato cliccato il pulsante. Nota che va bene usare un ref invece dello state qui perché il conteggio dei click viene letto e scritto solo in un gestore di eventi.

import { useRef } from 'react';

export default function Counter() {
  let ref = useRef(0);

  function handleClick() {
    ref.current = ref.current + 1;
    alert('You clicked ' + ref.current + ' times!');
  }

  return (
    <button onClick={handleClick}>
      Click me!
    </button>
  );
}

Se mostri {ref.current} nel JSX, il numero non si aggiornerà al click. Questo perché impostare ref.current non avvia una ri-renderizzazione. Le informazioni usate per la renderizzazione dovrebbero essere state.

Insidia

Non scrivere né leggere ref.current durante la renderizzazione.

React si aspetta che il corpo del tuo componente si comporti come una funzione pura:

  • Se gli input (props, state e context) sono gli stessi, dovrebbe restituire esattamente lo stesso JSX.
  • Chiamarlo in un ordine diverso o con argomenti diversi non dovrebbe influenzare i risultati delle altre chiamate.

Leggere o scrivere un ref durante la renderizzazione viola queste aspettative.

function MyComponent() {
// ...
// 🚩 Non scrivere un ref durante la renderizzazione
myRef.current = 123;
// ...
// 🚩 Non leggere un ref durante la renderizzazione
return <h1>{myOtherRef.current}</h1>;
}

Puoi leggere o scrivere i ref nei gestori di eventi o negli Effetti.

function MyComponent() {
// ...
useEffect(() => {
// ✅ Puoi leggere o scrivere ref negli Effetti
myRef.current = 123;
});
// ...
function handleClick() {
// ✅ Puoi leggere o scrivere ref nei gestori di eventi
doSomething(myOtherRef.current);
}
// ...
}

Se devi leggere o scrivere qualcosa durante la renderizzazione, usa lo state.

Quando violi queste regole, il tuo componente potrebbe funzionare comunque, ma la maggior parte delle funzionalità più recenti che stiamo aggiungendo a React si baserà su queste aspettative. Leggi di più su mantenere i tuoi componenti puri.


Manipolare il DOM con un ref

È particolarmente comune usare un ref per manipolare il DOM. React ha supporto integrato per questo.

Per prima cosa, dichiara un oggetto ref con un valore iniziale di null:

import { useRef } from 'react';

function MyComponent() {
const inputRef = useRef(null);
// ...

Poi passa il tuo oggetto ref come attributo ref al JSX del nodo DOM che vuoi manipolare:

// ...
return <input ref={inputRef} />;

Dopo che React crea il nodo DOM e lo mette sullo schermo, React imposterà la proprietà current del tuo oggetto ref su quel nodo DOM. Ora puoi accedere al nodo DOM dell’<input> e chiamare metodi come focus():

function handleClick() {
inputRef.current.focus();
}

React reimposterà la proprietà current su null quando il nodo viene rimosso dallo schermo.

Leggi di più su manipolare il DOM con i ref.

Esempi di manipolare il DOM con useRef

Esempio 1 di 4:
Mettere a fuoco un input di testo

In questo esempio, cliccare il pulsante metterà a fuoco l’input:

import { useRef } from 'react';

export default function Form() {
  const inputRef = useRef(null);

  function handleClick() {
    inputRef.current.focus();
  }

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleClick}>
        Focus the input
      </button>
    </>
  );
}


Evitare di ricreare il contenuto del ref

React salva il valore iniziale del ref una volta e lo ignora nelle renderizzazioni successive.

function Video() {
const playerRef = useRef(new VideoPlayer());
// ...

Sebbene il risultato di new VideoPlayer() venga usato solo per la renderizzazione iniziale, stai comunque chiamando questa funzione a ogni renderizzazione. Questo può essere inefficiente se crea oggetti costosi.

Per risolvere, puoi inizializzare il ref così:

function Video() {
const playerRef = useRef(null);
if (playerRef.current === null) {
playerRef.current = new VideoPlayer();
}
// ...

Normalmente, scrivere o leggere ref.current durante la renderizzazione non è consentito. Tuttavia, va bene in questo caso perché il risultato è sempre lo stesso, e la condizione viene eseguita solo durante l’inizializzazione, quindi è completamente prevedibile.

Approfondimento

Come evitare controlli null quando inizializzi useRef in seguito

Se usi un type checker e non vuoi controllare sempre null, puoi provare un pattern come questo:

function Video() {
const playerRef = useRef(null);

function getPlayer() {
if (playerRef.current !== null) {
return playerRef.current;
}
const player = new VideoPlayer();
playerRef.current = player;
return player;
}

// ...

Qui, playerRef stesso è nullable. Tuttavia, dovresti riuscire a convincere il tuo type checker che non c’è alcun caso in cui getPlayer() restituisca null. Poi usa getPlayer() nei tuoi gestori di eventi.


Troubleshooting

Non riesco a ottenere un ref a un componente personalizzato

Se provi a passare un ref al tuo componente così:

const inputRef = useRef(null);

return <MyInput ref={inputRef} />;

Potresti ottenere un errore nella console:

Console
TypeError: Cannot read properties of null

Per impostazione predefinita, i tuoi componenti non espongono ref ai nodi DOM al loro interno.

Per risolvere, trova il componente a cui vuoi ottenere un ref:

export default function MyInput({ value, onChange }) {
return (
<input
value={value}
onChange={onChange}
/>
);
}

E poi aggiungi ref all’elenco delle props che il tuo componente accetta e passa ref come prop al componente integrato figlio pertinente, così:

function MyInput({ value, onChange, ref }) {
return (
<input
value={value}
onChange={onChange}
ref={ref}
/>
);
};

export default MyInput;

Poi il componente genitore può ottenere un ref ad esso.

Leggi di più su accedere ai nodi DOM di un altro componente.