Comprendre et utiliser le Hook useRef en React
Le hook useRef
permet de créer une référence mutable qui persiste tout au long du cycle de vie du composant, sans déclencher de nouveau rendu lorsque sa valeur change.
Définition du hook useRef
- Il prend en paramètre une valeur initiale qui est affectée à la propriété
current
. - Il retourne un objet contenant une unique propriété
current
.
const ref = useRef(null);
Caractéristiques du hook useRef
- Modifier la valeur de
ref.current
n’entraîne pas un nouveau rendu du composant. - Le
useRef
est spécifique à chaque composant, donc si un composant est utilisé plusieurs fois, chaque instance aura sa propre référence distincte.
Principaux cas d'utilisation du hook useRef
1. Références DOM
L'une des utilisations principales de useRef
est de créer des références aux éléments DOM, permettant ainsi d'accéder et d'interagir avec des éléments HTML directement.
import { useRef, useEffect } from "react";
export default function MyApp() {
const ref = useRef(null);
useEffect(() => {
ref.current.focus();
}, []);
return <input type="text" ref={ref} />;
}
Lorsque l'élément HTML est supprimé, la valeur de ref.current
est automatiquement réinitialisée à null
.
2. Stockage de données persistantes entre les rendus
Le hook useRef
est également utile pour stocker des informations qui doivent persister entre les rendus mais ne doivent pas déclencher de ré-rendu lorsqu'elles sont mises à jour. Cela inclut des variables comme un timer ou des informations de la précédente interaction utilisateur.
const previousValue = useRef(null);
useEffect(() => {
previousValue.current = value; // Mémorise la valeur précédente sans provoquer de rendu
}, [value]);
Comment obtenir une référence à un composant enfant avec useRef ?
Vous pourriez instinctivement penser à passer une prop nommée ref
à un composant enfant pour lui assigner une référence à un élément DOM, comme dans l'exemple suivant :
import { useRef, useState, useEffect } from "react";
function MyInput({ value, onChange, ref }) {
return (
<input value={value} ref={ref} onChange={(e) => onChange(e.target.value)} />
);
}
export default function MyApp() {
const ref = useRef(null);
const [title, setTitle] = useState("");
useEffect(() => {
console.log(ref);
}, []);
return <MyInput value={title} ref={ref} onChange={setTitle} />;
}
Cependant, cette approche vous mènera à l'erreur suivante :
MyInput: `ref` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop.
En effet, dans React, la propriété ref
n'est pas une prop classique. Elle ne peut pas être directement transmise comme une prop standard aux composants enfants.
Solution 1 : Utiliser un nom de prop différent pour la référence
Une solution consiste à renommer la propriété utilisée pour la référence, par exemple en la nommant inputRef
au lieu de ref
. Ainsi, vous évitez d'entrer en conflit avec le comportement réservé de ref
.
import { useRef, useState, useEffect } from "react";
function MyInput({ value, onChange, inputRef }) {
return (
<input
value={value}
ref={inputRef}
onChange={(e) => onChange(e.target.value)}
/>
);
}
export default function MyApp() {
const ref = useRef(null);
const [title, setTitle] = useState("");
useEffect(() => {
console.log(ref);
}, []);
return <MyInput value={title} inputRef={ref} onChange={setTitle} />;
}
Solution 2 : Utiliser forwardRef pour transmettre la référence
Une autre solution plus appropriée consiste à utiliser la fonction forwardRef
de React, qui permet explicitement de transférer une référence depuis un composant parent vers un composant enfant.
import { useRef, useState, useEffect, forwardRef } from "react";
const MyInput = forwardRef(function ({ value, onChange }, ref) {
return (
<input value={value} ref={ref} onChange={(e) => onChange(e.target.value)} />
);
});
export default function MyApp() {
const ref = useRef(null);
const [title, setTitle] = useState("");
useEffect(() => {
console.log(ref);
}, []);
return <MyInput value={title} ref={ref} onChange={setTitle} />;
}
Dans React 19, les refs sont désormais transmises directement comme des props, éliminant ainsi le besoin d’utiliser forwardRef.