Skip to content
This page has been auto-translated and may contain errors.View in English

Hooks

Imagina que un componente necesita recordar si un dropdown está abierto, o necesita ejecutar código después de renderizarse para sincronizarse con un servidor. Ambas tareas son trabajo de un hook. Ya has usado dos: useState le da memoria a un componente, y useEffect ejecuta código después de un render para salir de React. Estos dos son los que usarás más, y el resto de los integrados siguen la misma estructura: llamas una función dentro de tu componente, y se conecta a una parte de la maquinaria de React. El nombre de esa función siempre empieza con use, y ese prefijo es la definición completa de un hook.

Un recorrido por los integrados más comunes

No necesitas cada hook el primer día, pero ayuda saber qué hay disponible para reconocer la herramienta correcta cuando un problema la pide. Aquí están los que aparecen más:

  • useRef sostiene un valor mutable que sobrevive los renders sin causarlos. También es cómo obtienes una referencia directa a un elemento del DOM cuando la necesitas, como para enfocar un input.
  • useContext lee datos compartidos de un provider alrededor, así un componente profundamente anidado puede alcanzar un valor sin que lo pases hacia abajo a través de cada nivel.
  • useReducer maneja el estado a través de una función reducer, donde cada actualización describe una transición del estado actual al siguiente. Es bueno cuando los cambios de estado se vuelven lo suficientemente complejos como para que un único useState empiece a fallar.
  • useMemo cachea un valor calculado entre renders y solo lo recalcula cuando sus dependencias cambian.
  • useCallback hace lo mismo para una función, dándote la misma instancia de función entre renders en lugar de una nueva cada vez.

useMemo y useCallback obtienen más atención después, cuando hay una historia real de rendimiento que contar. Refs y el DOM cubre useRef completamente. Para useContext y useReducer, este capítulo es el tratamiento más profundo que reciben, así que vuelve aquí cuando necesites un repaso. Por ahora, lo importante es el patrón: un hook es tu puerta a una característica específica de React, y su nombre te dice que es un hook.

Las reglas de los hooks

Los hooks vienen con dos reglas, y React cuenta con que las sigas.

Primero, llama hooks en el nivel superior de tu componente. No los llames dentro de una condición, un loop, o una función anidada. Cada hook que usa un componente debe ejecutarse en cada render, en el mismo orden, siempre.

jsx
function Profile({ isLoggedIn }) {
  // Incorrecto: este hook solo se ejecuta a veces
  if (isLoggedIn) {
    const [name, setName] = useState('')
  }

  // Correcto: llámalo en el nivel superior, incondicionalmente
  const [name, setName] = useState('')
  // ...luego usa isLoggedIn dentro de tu lógica
}

Segundo, solo llama hooks desde componentes React de función o desde otros hooks personalizados. Las funciones JavaScript normales no pueden usar hooks, porque no hay un render del componente para que React adjunte el estado.

Escribiendo tus propios hooks

Digamos que varios componentes necesitan conocer el ancho de la ventana del navegador. En lugar de copiar el mismo cableado de useState y useEffect en cada uno, puedes empaquetar esa lógica una sola vez:

jsx
import { useState, useEffect } from 'react'

function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth)

  useEffect(() => {
    const handleResize = () => setWidth(window.innerWidth)
    window.addEventListener('resize', handleResize)
    return () => window.removeEventListener('resize', handleResize)
  }, [])

  return width
}

Ahora cualquier componente puede llamar const width = useWindowWidth() y obtener un valor que se actualiza conforme la ventana cambia de tamaño. useWindowWidth es un hook personalizado: una función que llama otros hooks. Ese es el patrón completo, y como es una función, puedes darle un nombre a un pedazo de lógica con estado, ponerlo en un lugar, y reutilizarlo entre componentes. El prefijo use es lo que lo marca como un hook, tanto para la herramienta de React como para la próxima persona que lee tu código. Los hooks personalizados empaquetan los hooks que ya tienes en algo reutilizable; no agregan nuevos poderes a React.

Algunas reglas prácticas para elegir de esa lista. Usa useRef cuando necesites sostener un valor, como un ID de temporizador o una prop anterior, que no debería causar un re-render cuando cambia, o cuando necesites agarrar un nodo del DOM directamente. Usa useContext cuando un valor como el tema actual o el usuario conectado necesita llegar a varios niveles de componentes anidados, y pasarlo a través de props en cada nivel significaría tocar componentes que no se preocupan por ello. Usa useReducer cuando una sola pieza de estado tiene varios sub-valores que se actualizan juntos, o cuando el próximo estado depende de una acción específica en lugar de un valor nuevo simple, porque un reducer mantiene esa lógica de transición en una función en lugar de dispersarla entre varios llamados setState. Usa useMemo o useCallback solo después de que hayas notado un desempeño lento real, frecuentemente un cálculo costoso que se ejecuta nuevamente en cada render, o una identidad de función que está rompiendo memoización en otro lugar, como un hijo con React.memo o el array de dependencias de otro hook.

Nombrar y extraer un hook personalizado sigue un patrón propio. El nombre siempre empieza con use, así la herramienta de React y cualquiera que lea el código puede saber que se permite llamar otros hooks. Cuando notes la misma combinación de useState y useEffect, u otros hooks cualesquiera, apareciendo en más de un componente, esa es la señal de extraer: saca la lógica a su propia función con prefijo use, haz que devuelva lo que los componentes realmente necesitan, un valor, un setter, o un par de ambos, y llama esa función desde cada componente en lugar de repetir el cableado.

Las reglas no son arbitrarias. React no conoce los nombres de tus variables de estado; rastrea los hooks en un componente por el orden en que se llaman. Primer hook, segundo hook, tercer hook, y así sucesivamente. En el próximo render camina esa misma lista en el mismo orden e iguala cada llamada de vuelta al estado que configuró la última vez. Mantén el orden idéntico en cada render y la correspondencia se sostiene. Pon un hook detrás de una condición y la lista se desplaza en el momento que esa condición se voltea, así React alinea el estado incorrecto con la llamada incorrecta y el componente se rompe de formas confusas. Llamar en el nivel superior, incondicionalmente, es lo que garantiza un orden estable.

useMemo y useCallback merecen una nota aparte. Son optimizaciones manuales: le estás diciendo a React que sostenga un valor calculado o una función para que no tenga que rehacer el trabajo o entregar una nueva instancia en cada render. Te cuestan algo de complejidad, y es tentador usarlos donde realmente no ayudan. React Compiler cada vez más los hace innecesarios memorizando este tipo de cosa por ti en tiempo de construcción, así que trata alcanzar ellos manualmente como algo que haces deliberadamente, donde has medido un costo real, en lugar de un reflejo en cada valor.

JunoLos hooks dejan que un componente use características de React Un hook es una función cuyo nombre empieza con use, y conecta tu componente a una característica de React como memoria o efectos. Ya conoces useState y useEffect, y los otros siguen la misma forma. Lo principal que recordar: llama hooks en la cima de tu componente, nunca dentro de un if o un loop, para que se ejecuten de la misma manera cada render.
JunoLos hooks dejan que un componente use características de React Además de useState y useEffect, tienes useRef para valores que sobreviven renders sin causar uno, useContext para evitar prop drilling, useReducer para transiciones de estado estructuradas, y useMemo/useCallback para cachear. Llámalos en el nivel superior de un componente u otro hook, siempre en el mismo orden. Cuando te encuentres repitiendo lógica con estado, extráela a un hook personalizado, una función use que llama otros hooks, y reutilízala.
JunoLos hooks dejan que un componente use características de React React iguala hooks a su estado por orden de llamada, no por nombre, así el orden tiene que ser idéntico en cada render. Ese hecho único es de donde vienen ambas reglas. Los hooks personalizados son composición: una función llamando hooks, por eso las mismas reglas de orden aplican dentro de ellos. Y trata useMemo/useCallback como optimizaciones deliberadas y medidas, porque React Compiler está haciendo constantemente las versiones escritas a mano innecesarias.

Próximo: Pensando en React, donde componentes, props, estado, y efectos se juntan en un proceso para convertir un diseño en una UI.