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 menú desplegable está abierto, o necesita ejecutar código después de renderizarse para sincronizarse con un servidor. Ambas son tareas para un hook. Ya usaste dos: useState le da memoria a un componente, y useEffect ejecuta código después de un render para comunicarte con el mundo exterior de React. Esos dos los usarás más, y el resto de los built-ins siguen la misma estructura: llamas una función dentro de tu componente, y te conecta con parte de la maquinaria de React. El nombre de esa función siempre empieza con use, y ese prefijo es toda la definición de un hook.

Un recorrido por los built-ins más comunes

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

  • useRef guarda un valor mutable que sobrevive a los renders sin causar uno. También es la forma de obtener una referencia directa a un elemento del DOM cuando lo necesitas, como para enfocar un input.
  • useContext lee datos compartidos de un provider circundante, así un componente profundamente anidado puede acceder a un valor sin que lo pases por cada nivel intermedio.
  • useReducer maneja el estado a través de una función reductora, donde cada actualización describe una transición del estado actual al siguiente. Es útil cuando los cambios de estado se vuelven lo suficientemente complejos para que un solo useState empiece a quedarse corto.
  • 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 tienen más espacio en Memoización, una vez que hay una historia real de rendimiento que contar. Refs y el DOM profundiza en useRef, y Context lleva useContext de este resumen hasta providers y estado compartido. Para useReducer, este capítulo es el tratamiento más profundo que recibe, así que vuelve aquí cuando necesites refrescar. Por ahora, el punto es el patrón: un hook es tu forma de acceder 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 bucle, o una función anidada. Cada hook que use un componente debe ejecutarse en cada render, en el mismo orden, siempre.

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

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

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

Escribir tus propios hooks

Digamos que varios componentes necesitan saber el ancho de la ventana del navegador. En lugar de copiar el mismo código 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 cuando la ventana cambia de tamaño. useWindowWidth es un hook personalizado: una función que llama otros hooks. Ese es todo el patrón, y porque es una función, puedes darle un nombre a una pieza de lógica stateful, ponerla en un solo lugar, y reutilizarla entre componentes. El prefijo use es lo que lo marca como hook, tanto para las herramientas de React como para la próxima persona que lea tu código. Los hooks personalizados agrupan los hooks que ya tienes en algo reutilizable; no añaden nuevas capacidades a React.

Algunas reglas prácticas para elegir de esa lista. Usa useRef cuando necesites guardar un valor, como un ID de temporizador o una prop anterior, que no debe disparar un re-render cuando cambia, o cuando necesites acceder directamente a un nodo del DOM. Usa useContext cuando un valor como el tema actual o el usuario conectado necesita llegar a varios niveles de componentes anidados, y pasar eso por props en cada nivel significaría tocar componentes que no les importa. Usa useReducer cuando una sola pieza de estado tiene varios sub-valores que se actualizan juntos, o cuando el siguiente estado depende de una acción específica en lugar de solo un nuevo valor, ya que una reductora mantiene esa lógica de transición en una función en lugar de dispersarla entre varias llamadas a setState. Usa useMemo o useCallback solo después de que hayas notado una desaceleración real, más frecuentemente un cálculo costoso que se ejecuta en cada render, o una identidad de función que está rompiendo memoización en otro lugar, como un hijo envuelto en React.memo o el array de dependencias de otro hook.

Nombrar y extraer un hook personalizado sigue su propio patrón. El nombre siempre empieza con use, así tanto las herramientas de React como cualquiera leyendo el código puede saber que puede llamar otros hooks. Cuando notices la misma combinación de useState y useEffect, o cualquier otros hooks, apareciendo en más de un componente, esa es la señal para extraer: saca la lógica en su propia función con prefijo use y llámala desde cada componente en lugar de repetir el código. Hooks personalizados en la práctica va más lejos, a qué debe retornar un hook y cómo diseñar sus opciones.

Las reglas no son arbitrarias. React no conoce los nombres de tus variables de estado; sigue los hooks en un componente por el orden en que se llaman. Primer hook, segundo hook, tercer hook, y así sucesivamente. En el siguiente render recorre esa misma lista en el mismo orden y asocia cada llamada al estado que configuró la última vez. Mantén el orden idéntico en cada render y la asociación se sostiene. Pon un hook detrás de una condición y la lista se desplaza en el momento en que esa condición cambia, así React alinea el estado equivocado con la llamada equivocada y el componente se rompe de formas confusas. Llamar en el nivel superior, sin condiciones, es lo que garantiza un orden estable.

useMemo y useCallback merecen una nota aparte. Son optimizaciones manuales: le dices a React que guarde un valor calculado o una función así no tiene que rehacer el trabajo o entregar una nueva instancia en cada render. Te cuestan algo de complejidad, y es tentador usarlos donde no realmente ayudan. El Compilador de React cada vez más los hace innecesarios memoizando este tipo de cosas por ti en tiempo de construcción, así que trata llegar por ellos manualmente como algo que haces deliberadamente, donde mediste un costo real, en lugar de un reflejo en cada valor.

JunoLos hooks permiten a un componente usar 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 conociste useState y useEffect, y los otros siguen la misma estructura.

Lo principal que recordar: llama hooks en el tope de tu componente, nunca dentro de un if o un bucle, así se ejecutan igual en cada render.

JunoLos hooks permiten a un componente usar características de React Además de useState y useEffect, tienes useRef para valores que sobreviven renders sin disparar uno, useContext para evitar prop drilling, useReducer para transiciones de estado estructuradas, y useMemo/useCallback para cachear.

Llámales en el nivel superior de un componente u otro hook, siempre en el mismo orden.

Cuando te encuentres repitiendo lógica stateful, extráela en un hook personalizado, una función use que llama otros hooks, y reutilízalo.

JunoLos hooks permiten a un componente usar características de React React asocia hooks a su estado por orden de llamada en lugar de por nombre, así el orden tiene que ser idéntico en cada render. Ese hecho singular es de donde vienen ambas reglas.

Los hooks personalizados son composición: una función que llama hooks, es por eso que las mismas reglas de orden aplican dentro de ellos.

Y trata useMemo/useCallback como optimizaciones deliberadas y medidas, ya que el Compilador de React está haciendo constantemente innecesarias las versiones escritas a mano.

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