Más hooks: useRef, useReducer y hooks propios
💡 🎯 Al terminar esta lección podrás…
- Acceder al DOM y guardar valores mutables con
useRef. - Organizar estados complejos con
useReducer. - Saber cuándo (y cuándo no) memorizar.
- Crear y reutilizar hooks personalizados.
1.useRef: una referencia que no provoca dibujos
useRef devuelve un objeto que se conserva entre dibujos y cuya propiedad .current puedes leer y cambiar sin que React vuelva a dibujar. Tiene dos usos principales:
| Uso | Ejemplo |
|---|---|
| Acceder a un elemento del DOM | Enfocar un campo, hacer scroll, medir un tamaño, reproducir un video |
| Guardar un valor mutable que no se muestra | El id de un temporizador, el valor anterior de algo, un contador interno |
⚠️ Importante · Estado frente a referencia
Si el valor se muestra en pantalla, debe ser estado. Si solo lo necesitas «recordar» sin dibujarlo, usa una referencia. No leas ni escribas ref.current mientras dibujas (en el cuerpo del componente): hazlo en eventos y efectos.
2.useReducer: estado con muchas acciones
Cuando un estado tiene muchas formas de cambiar (agregar, quitar, editar, vaciar…), repartir setX por todo el componente se desordena. useReducer concentra toda la lógica en una sola función, el reductor, que recibe el estado actual y una acción y devuelve el estado nuevo.
useState | useReducer |
|---|---|
| Estados simples (un número, un texto, un booleano) | Estados complejos (objetos con varias partes o listas con muchas operaciones) |
| Pocas formas de cambiar | Muchas acciones relacionadas |
| La lógica está en los manejadores de eventos | La lógica está centralizada y es fácil de probar |
💡 Consejo · Reductor + Context
La combinación useReducer + Context es la «mini Redux» que muchas aplicaciones medianas necesitan. La verás completa en el proyecto final.
3.useMemo y useCallback: optimizar con cabeza
React es rápido por defecto. Solo cuando midas un problema de rendimiento te servirán estas dos herramientas, que recuerdan un resultado entre dibujos:
| Hook | Recuerda… | Se recalcula cuando… |
|---|---|---|
useMemo(() => cálculo, [deps]) | El resultado de un cálculo costoso | cambia alguna dependencia |
useCallback(fn, [deps]) | La función misma (misma referencia) | cambia alguna dependencia |
⚠️ Importante · No los uses «por si acaso»
Memorizar tiene un costo (memoria y código más difícil de leer). Empieza sin ellos, mide con las herramientas de desarrollo y úsalos donde de verdad haya lentitud. useCallback solo aporta algo cuando pasas la función a un componente envuelto en memo o a las dependencias de un efecto.
4.Hooks personalizados: reutilizar lógica
Un hook personalizado es una función cuyo nombre empieza por use y que usa otros hooks dentro. Sirve para extraer lógica con estado y reutilizarla en varios componentes, igual que un componente reutiliza JSX.
📌 Nota · Se comparte la lógica, no el estado
Cada vez que usas un hook personalizado, cada componente obtiene su propio estado. Los dos <Votos /> tienen contadores separados aunque usen el mismo hook.
function useLocalStorage(clave, inicial) {
const [valor, setValor] = useState(() => {
const guardado = localStorage.getItem(clave);
return guardado !== null ? JSON.parse(guardado) : inicial;
});
useEffect(() => {
localStorage.setItem(clave, JSON.stringify(valor));
}, [clave, valor]);
return [valor, setValor];
}
// Se usa igual que useState, pero persiste
const [nombre, setNombre] = useLocalStorage("nombre", "");
5.Las reglas de los hooks
- Solo en el nivel superior: no los llames dentro de
if, bucles ni funciones anidadas. - Solo en componentes o en otros hooks: no en funciones normales de JavaScript.
- Los hooks personalizados empiezan por
use: así las herramientas reconocen que son hooks y vigilan las reglas.
💡 Consejo · Instala el linter
Los proyectos de Vite traen eslint-plugin-react-hooks, que te avisa si rompes estas reglas o si olvidas una dependencia. Es de las ayudas más valiosas al aprender.
6.Errores frecuentes
- Usar
ref.currentpara algo que se muestra: la pantalla no se actualizará; usa estado. - Leer
ref.currentmientras dibujas: puede estarnullen el primer dibujo. - Mutar el estado dentro del reductor: debe devolver siempre un objeto nuevo.
- Olvidar el
defaultdel reductor: una acción mal escrita pasa desapercibida. - Usar
useMemopor todas partes: añade complejidad sin beneficio medido. - Dependencias incompletas en
useMemoyuseCallback: devuelven valores viejos. - Un hook personalizado sin
useal inicio: React no puede comprobar las reglas.
📒 Apuntes para llevar
useRefguarda un valor mutable que no redibuja y da acceso a elementos del DOM (ref={campo}→campo.current).- Si se muestra en pantalla, es estado; si solo se recuerda, es ref.
useReducer(reductor, inicial)centraliza los cambios de un estado complejo con acciones (dispatch({ tipo })).- El reductor es una función pura:
(estado, acción) → estado nuevo. useMemorecuerda un resultado;useCallbackrecuerda una función. Úsalos solo si mides un problema.- Un hook personalizado (
useAlgo) extrae lógica con estado para reutilizarla. - Reglas de los hooks: nivel superior y solo en componentes u otros hooks.
7.Glosario
| Término | Significado |
|---|---|
useRef | Hook que devuelve un objeto { current } estable entre dibujos. |
useReducer | Hook para manejar estado complejo mediante un reductor y acciones. |
| Reductor (reducer) | Función pura que recibe estado y acción y devuelve el nuevo estado. |
| Acción | Objeto que describe qué ocurrió, por ejemplo { tipo: "sumar" }. |
useMemo | Hook que recuerda el resultado de un cálculo mientras no cambien sus dependencias. |
useCallback | Hook que recuerda una función con la misma referencia entre dibujos. |
| Hook personalizado | Función useAlgo que reutiliza lógica con hooks entre componentes. |
🧠 Comprueba lo aprendido
Elige una respuesta en cada pregunta. Verás al instante si acertaste y por qué.
¿Qué ocurre al cambiar miRef.current?
Las referencias no provocan nuevos dibujos.
Necesitas enfocar un <input> al pulsar un botón. ¿Qué usas?
Con ref={campo} accedes al elemento real y llamas a campo.current.focus().
¿Qué debe devolver un reductor?
Es una función pura: crea siempre un estado nuevo.
¿Cuál es un nombre válido para un hook personalizado?
Los hooks personalizados empiezan por use.
¿Cuándo conviene usar useMemo?
Es una optimización: úsala donde haya un problema real de rendimiento.
Tu progreso se guarda en este navegador y se refleja en el índice del curso.
💡 🚀 ¡Ahora te toca!
La práctica fija lo aprendido. Pasa al ejercicio de esta lección.