Join the discussion
Comments
Loading comments...
Cookie preferences
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Join the discussion
Loading comments...
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Comment useRef persiste les valeurs mutables entre les rendus et fournit un accès direct au DOM.
useRef retourne un objet mutable { current: valeur } qui persiste pendant toute la durée de vie du composant. Contrairement au state, muter ref.current ne déclenche PAS un re-rendu. React utilise aussi les refs comme trappe de secours pour l'accès direct au DOM — après la phase de commit, React définit ref.current sur le vrai nœud DOM, vous donnant un accès impératif à l'API du navigateur.
Au premier rendu, useRef(initialValue) crée l'objet '{' current: initialValue '}' et le stocke sur la liste des hooks du fiber. À chaque rendu suivant, React retourne le même objet — donc ref.current pointe toujours vers la même boîte.
React ne suit pas les mutations de ref.current. Lorsque vous écrivez ref.current = 5, React n'en a aucune idée et ne planifiera pas de re-rendu. Cela rend les refs idéales pour les valeurs que vous souhaitez persister mais n'avez pas besoin d'afficher.
Lorsque vous passez une ref à un élément JSX (<input ref='{'maRef'}' />), React ne définit pas ref.current pendant la phase de rendu. Il attend la phase de commit — après que le nœud DOM existe — puis définit ref.current = nœudDom.
Lorsque le composant se démonte, React définit ref.current = null avant d'exécuter les effets de nettoyage. Cela empêche vos effets d'accéder à un nœud DOM détaché.
Par défaut, les refs ne peuvent pas être attachées à des composants fonctionnels. Utilisez forwardRef pour accepter une prop ref et la transmettre à un élément DOM ou exposer des méthodes impératives via useImperativeHandle.
L'objet ref. React vous donne le même objet à chaque rendu. Mutez current librement — aucun re-rendu ne se produira.
Passez une ref à un élément JSX pour obtenir le nœud DOM sous-jacent dans ref.current après le commit. Utile pour le focus, le défilement et les mesures.
Enveloppe un composant fonctionnel pour accepter une prop ref et la transmettre à un élément interne ou l'exposer via useImperativeHandle.
Personnalise ce que le parent voit lorsqu'il accède à la ref d'un enfant. Au lieu du nœud DOM, vous pouvez exposer des méthodes spécifiques.
Utilisez le state pour les valeurs qui affectent l'interface (déclenche un re-rendu). Utilisez les refs pour les valeurs qui n'affectent pas le rendu : timers, nœuds DOM, valeurs précédentes, indicateurs.
1// 1. DOM access — focus an input programmatically2const inputRef = useRef(null);3<input ref={inputRef} />4// After mount: inputRef.current is the <input> DOM node5inputRef.current.focus(); // imperative DOM call67// 2. Persist a value without re-rendering8const timerRef = useRef(null);9timerRef.current = setInterval(tick, 1000);10// Later:11clearInterval(timerRef.current);1213// 3. Read latest state in a stale closure14const countRef = useRef(count);15countRef.current = count; // sync on every render16useEffect(() => {17 const interval = setInterval(() => {18 console.log(countRef.current); // always latest value19 }, 1000);20 return () => clearInterval(interval);21}, []); // empty deps — no stale closure problem
Les refs sont la trappe de secours officielle de React pour le code impératif. Elles vous permettent de faire le pont entre le monde déclaratif de React et les APIs du navigateur qui nécessitent des appels impératifs (focus, défilement, animations, bibliothèques DOM tierces). Elles résolvent aussi le problème de closure périmée dans les effets — en maintenant une ref synchronisée avec le dernier state, vous pouvez accéder en toute sécurité aux valeurs courantes dans les opérations asynchrones de longue durée.
A multi-step checkout form should automatically focus the first empty field when the user navigates to a new step. Using state to track focus causes infinite re-renders.
Attempting to manage focus with useState creates a loop: setState triggers re-render, re-render re-focuses, which fires onFocus, which might set state again. Focus is an imperative DOM operation — it doesn't fit React's declarative model.
Use a ref to directly call `.focus()` on the input DOM node: `useEffect(() => { inputRef.current?.focus() }, [currentStep])`. The ref gives you direct DOM access without triggering re-renders. Focus management is inherently imperative — refs are React's bridge to imperative DOM APIs.
Takeaway: Use refs for imperative DOM operations that don't produce visual output (focus, scroll, measure, select text, play/pause media). These operations are side effects that bypass React's virtual DOM — refs give you a controlled escape hatch.
You need to compare the current value with the previous value to show a 'price changed' animation. Storing the previous value in state causes an extra re-render on every change.
Using `useState(previousPrice)` to track the old price means: price changes → re-render with new price → useEffect sets previousPrice → ANOTHER re-render. Two renders for one price change, and the animation triggers late.
Use a ref: `const prevPriceRef = useRef(price)`. In useEffect, compare `price !== prevPriceRef.current`, trigger the animation, then update: `prevPriceRef.current = price`. Refs update without re-rendering — you get the comparison for free, no extra render cycle.
Takeaway: Refs are the correct tool for 'instance variables' — values that need to persist across renders but shouldn't trigger re-renders when updated. Common patterns: previous values, timer IDs, DOM nodes, external library instances, and accumulator values.