📋 Tabla de contenidos
-
useState
– El fundamento del estado -
useEffect
– Efectos secundarios y ciclo de vida -
useContext
– Compartir estado sin props -
useReducer
– Lógica de Estado Compleja y predecible -
useRef
– Referencias, Almacenamiento y Escape -
useMemo
yuseCallback
– Optimizando el Rendimiento - Custom Hooks – Creando Lógica Reutilizable
- Errores Comunes y Soluciones
¿Qué es y para qué sirve?
useRef
es un hook versátil con dos casos de uso principales que, aunque parezcan diferentes, se basan en el mismo principio: proporcionar un objeto mutable (.current
) que persiste durante todo el ciclo de vida del componente sin causar re-renderizados cuando cambia.
- Acceder a elementos del DOM: Es la "salida de emergencia" para interactuar directamente con un elemento del DOM, por ejemplo, para manejar el foco, medir su tamaño o integrar librerías de terceros (como D3.js).
- Guardar "variables de instancia": Te permite mantener un valor mutable que no necesita disparar una nueva renderización. Es como tener una variable de instancia en un componente de clase. Perfecto para guardar IDs de timers, contadores internos, o cualquier valor que necesites que sobreviva entre renders.
Sintaxis y características clave
const miRef = useRef(valorInicial);
-
useRef
devuelve un objeto con una única propiedad:current
. -
miRef.current
se inicializa convalorInicial
. - Puedes cambiar
miRef.current
directamente:miRef.current = nuevoValor
. - Importante: Cambiar
miRef.current
NO dispara un re-renderizado.
Ejemplo práctico detallado: input con foco y contador de renders
Este ejemplo muestra ambos usos de useRef
: uno para el DOM y otro para una variable persistente.
import React, { useState, useEffect, useRef } from 'react';
function FocusCounter() {
const [inputValue, setInputValue] = useState('');
// Caso de uso 1: Referencia al DOM
const inputRef = useRef(null);
// Caso de uso 2: Variable persistente
const renderCount = useRef(0);
useEffect(() => {
// Se ejecuta después de cada render
renderCount.current = renderCount.current + 1;
});
const handleFocus = () => {
// Accedemos al elemento del DOM directamente
inputRef.current.focus();
};
return (
<div>
<h3>Ejemplo de useRef</h3>
<input
ref={inputRef} // Conectamos la ref al elemento input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Escribe algo..."
/>
<button onClick={handleFocus}>Poner Foco en el Input</button>
<p>El valor del input es: "{inputValue}"</p>
<p>Este componente se ha renderizado {renderCount.current} veces.</p>
<p>(Nota: el contador de renders no causa re-renders por sí mismo)</p>
</div>
);
}
En este ejemplo:
-
inputRef
nos da acceso directo al<input>
, permitiéndonos llamar a.focus()
. -
renderCount
lleva la cuenta de las renderizaciones. Si usáramosuseState
para esto, cada actualización del contador causaría otro render, creando un bucle infinito. ConuseRef
, podemos actualizar el valor sin efectos secundarios.
✅ Buenas practicas y patrones comunes
- Cuándo usar
useRef
vsuseState
:- Usa
useState
si el cambio en el valor debe ser visible en la UI. - Usa
useRef
si necesitas que un valor persista entre renders pero no quieres que su cambio dispare una nueva renderización.
- Usa
-
Guardar el valor previo de props o estado: Un patrón muy útil es combinar
useRef
yuseEffect
para "recordar" un valor del render anterior.
function Componente({ valor }) { const valorPrevioRef = useRef(); useEffect(() => { valorPrevioRef.current = valor; }, [valor]); // Se actualiza después de que el render se completa const valorPrevio = valorPrevioRef.current; // ... }
Manejo de Timers:
useRef
es ideal para guardar el ID desetInterval
osetTimeout
para poder limpiarlo después.
🚨 Errores comunes y cómo evitarlos
-
Error: Acceder a
ref.current
demasiado pronto.
// MAL ❌ function MiComponente() { const miRef = useRef(null); // Aquí, durante el primer render, miRef.current es `null` // porque el DOM aún no existe. Esto dará un error. miRef.current.focus(); return <input ref={miRef} />; }
- Solución: Accede a la ref dentro de un
useEffect
(que se ejecuta después del renderizado) o en manejadores de eventos (que se ejecutan por interacción del usuario).
// BIEN ✅ useEffect(() => { // Para el primer render, esto se ejecuta después de que el input existe. miRef.current.focus(); }, []); // Array vacío para que solo se ejecute una vez
- Solución: Accede a la ref dentro de un
-
Error: Mostrar el valor de una ref en la UI y esperar que se actualice.
- Solución: Si necesitas que un cambio se refleje en el render, ese valor debe estar en el estado (
useState
). Recuerda:useRef
no notifica a React cuando cambia.
- Solución: Si necesitas que un cambio se refleje en el render, ese valor debe estar en el estado (
🚀 Retos prácticos
- Reproductor de Video: Crea un componente que muestre un video (
<video>
). UsauseRef
para obtener una referencia al elemento y añade botones para "Play", "Pause" y "Stop". - Cronómetro Preciso: Haz un cronómetro que use
setInterval
. Guarda el ID del intervalo en una ref para poder detenerlo y reiniciarlo correctamente. - Scroll a un Elemento: Crea una lista larga de elementos. Añade botones al principio que, al hacer clic, hagan scroll automáticamente a un elemento específico en medio de la lista (pista:
element.scrollIntoView()
).
Top comments (0)