Passer au contenu principal

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.