
Différences entre `useRef` et le state
Analyse comparative détaillée entre le hook useRef et les hooks de state (useState, useReducer) en React : re-renders, mutabilité, accès et cas d'usage.
Introduction : Deux mécanismes de persistance, deux rôles distincts
A première vue, `useRef` et les hooks de state (`useState`, `useReducer`) peuvent sembler partager une caractéristique : ils permettent tous deux de conserver des informations qui persistent entre les différents rendus d'un composant fonctionnel. Cependant, leurs objectifs, leurs mécanismes et leurs implications sur le comportement du composant sont fondamentalement différents.
Une confusion fréquente, surtout chez les débutants, est de savoir quand utiliser l'un plutôt que l'autre. Comprendre leurs distinctions fondamentales est essentiel pour écrire du code React correct, performant et idiomatique. Cette section vise à clarifier ces différences clés.
Différence n°1 (La plus importante) : Le déclenchement des re-renders
C'est la distinction la plus cruciale :
- State (`useState`, `useReducer`) : La modification de l'état via sa fonction de mise à jour (
setStateoudispatch) signale à React qu'il doit planifier un re-rendu du composant (et de ses enfants). C'est le mécanisme principal par lequel React met à jour l'interface utilisateur en réponse à des changements de données. Le state est conçu pour contenir des données dont les changements doivent être reflétés visuellement. - `useRef` : La modification directe de la propriété
.currentd'une ref (maRef.current = nouvelleValeur) ne déclenche absolument aucun re-rendu. React ne surveille pas les changements de la propriété.current. Les refs sont conçues pour conserver des informations qui ne font pas partie intégrante de l'état visuel du composant ou pour interagir avec des systèmes externes (comme le DOM) de manière impérative.
En résumé : si un changement de valeur doit mettre à jour ce que l'utilisateur voit, utilisez le state. Si un changement de valeur doit être conservé sans affecter l'UI, ou s'il sert à interagir avec le DOM, utilisez `useRef`.
Différence n°2 : La méthode de mise à jour
La manière dont vous modifiez la valeur diffère également :
- State (`useState`, `useReducer`) : Vous ne devez jamais muter l'état directement. Vous devez toujours utiliser la fonction de mise à jour fournie (
setStateoudispatch). React utilise cette fonction pour planifier le re-rendu et garantir la cohérence. Les mises à jour d'état sont souvent asynchrones et peuvent être groupées (batched) par React. - `useRef` : La valeur est contenue dans la propriété
.current, qui est mutable. Vous mettez à jour la valeur en assignant directement une nouvelle valeur à cette propriété :maRef.current = .... Cette modification est synchrone et immédiate.
Différence n°3 : L'accès à la valeur
Comment vous lisez la valeur actuelle :
- State (`useState`, `useReducer`) : Vous accédez directement à la variable d'état retournée par le hook (par exemple,
countdansconst [count, setCount] = useState(0)). Cette variable contient toujours la valeur de l'état pour le rendu *actuel*. - `useRef` : Vous accédez à la valeur via la propriété
.currentde l'objet ref (maRef.current). Cette propriété contient la dernière valeur qui lui a été assignée, et cette valeur est la même à travers tous les rendus jusqu'à ce qu'elle soit explicitement modifiée. (Rappel : pour les refs DOM,.currentn'est assigné qu'après le rendu).
Différence n°4 : Les cas d'usage principaux
Leurs différences fondamentales dictent leurs utilisations typiques :
- State (`useState`, `useReducer`) :
- Gérer les données qui déterminent ce qui est affiché à l'écran.
- Répondre aux interactions utilisateur qui doivent modifier l'UI (clics, saisie formulaire, etc.).
- Gérer l'état de chargement, les erreurs, les données reçues d'API qui doivent être affichées.
- En bref : tout ce qui est lié au rendu et à l'état visuel du composant.
- `useRef` :
- Accéder et interagir avec des noeuds DOM spécifiques (focus, mesures, API médias, intégration de libs tierces).
- Stocker des valeurs mutables qui doivent persister entre les rendus sans causer de re-rendu (ID de timers, indicateurs internes, valeur précédente d'une prop/state, instances de classes ou de connexions).
- En bref : interaction impérative avec le DOM ou stockage de données "silencieuses" non liées au rendu.
Tableau comparatif résumé
| Caractéristique | State (`useState`/`useReducer`) | `useRef` |
|---|---|---|
| Cause un re-rendu si modifié ? | Oui (via setter/dispatch) | Non (modification de .current) |
| Méthode de mise à jour | Via fonction setter/dispatch (asynchrone potentiellement) | Assignation directe à .current (synchrone) |
| Mutabilité | Immuable (ne pas modifier directement) | Mutable (via .current) |
| Accès à la valeur | Variable d'état directe | Propriété .current |
| Persistance entre rendus | Oui | Oui |
| Usage principal | Données pilotant l'UI | Accès DOM, valeurs persistantes non-visuelles |
Conclusion : Choisir le bon outil pour le bon travail
Bien que `useRef` et les hooks de state permettent tous deux de conserver des valeurs, ils servent des objectifs très différents dans l'écosystème React. Le state est au coeur du modèle déclaratif et réactif de React, liant les données à l'interface utilisateur. `useRef`, quant à lui, offre une échappatoire pour des besoins impératifs (DOM) ou pour gérer des données persistantes qui ne doivent pas influencer le cycle de rendu.
Choisir consciemment entre `useRef` et le state en fonction de la nécessité ou non de déclencher un re-rendu lors d'un changement est une compétence fondamentale pour écrire des composants React efficaces, performants et faciles à comprendre.