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

Elevar el estado

Un input de texto está al lado de una vista previa que necesita mostrar lo que se ha escrito. Ambos viven en el mismo árbol de componentes, pero el estado declarado dentro de un componente es invisible para sus vecinos, así que ni el input ni la vista previa pueden leer o cambiar lo que el otro tiene. La solución es mover ese estado al componente padre que comparten ambos, y luego pasar el valor a cada uno como prop. Esto se llama elevar el estado.

Acá está ese par, compartiendo un valor:

jsx
import { useState } from 'react'

function Form() {
  const [text, setText] = useState('')

  return (
    <>
      <TextInput text={text} onChange={setText} />
      <TextDisplay text={text} />
    </>
  )
}

function TextInput({ text, onChange }) {
  return <input value={text} onChange={e => onChange(e.target.value)} />
}

function TextDisplay({ text }) {
  return <p>Escribiste: {text}</p>
}

Form es el padre común más cercano de TextInput y TextDisplay, así que ahí es donde vive text. Pasa text a ambos, y pasa setText a TextInput con el nombre onChange. Cuando alguien escribe, TextInput llama a onChange con el nuevo valor, el estado de Form se actualiza, y Form se re-renderiza. Ese re-render envía el nuevo text hacia abajo a ambos hijos, así que TextDisplay muestra exactamente lo que hay en el input sin mantener estado propio.

Mantén el estado tan bajo como sea posible

Elevar el estado es un movimiento que haces solo cuando lo necesitas. La regla de oro es colocación de estado: mantén cada parte del estado tan baja en el árbol como pueda vivir, cerca del componente que realmente la usa, y elévala solo cuando algo más también necesita leerla o cambiarla. Un componente con estado que nadie toca debe mantener ese estado para sí mismo.

Esto importa porque elevar tiene un costo. Cada nivel que una parte del estado sube, el padre tiene que pasarla de nuevo hacia abajo como prop, y cada componente en el medio tiene que aceptar y pasar adelante esa prop aunque nunca use el valor. Empieza local. Eleva el estado solo hasta el componente más cercano que realmente necesita compartirlo, y no más.

Pasar el setter hacia abajo

Nota que Form no solo pasa text hacia abajo. También pasa setText, como la prop onChange. Esta es la otra mitad de elevar el estado: el componente que es dueño del estado entrega una manera de cambiarlo mediante props, y el hijo llama a esa función en lugar de manejar el valor por sí mismo. TextInput nunca ve setText directamente. Llama a cualquier función que le dieron, y el padre decide qué hace realmente esa función.

Para estado compartido entre componentes anidados muchos niveles más abajo, pasar props hacia abajo a través de cada capa deja de ser práctico. React tiene herramientas para ese caso, Context entre ellas, y Context cubre useContext, el hook que lee un valor sin pasarlo a través de cada componente en el medio. Eso va más allá de lo que este capítulo cubre; el patrón de arriba es el que deberías usar primero.

Elige un componente para que sea dueño de una parte del estado y trátalo como la única fuente de verdad para ese valor. No dejes que un segundo componente tenga una copia del mismo dato en su propio estado e intente mantener las dos sincronizadas manualmente. Dos copias del mismo valor se desvían la momento en que se pierde una ruta de actualización, y perseguir ese bug es peor que los props extra que habría costado elevar el estado desde el principio. Si un valor se puede derivar del estado que ya existe en algún lugar, derívalo durante el render en lugar de almacenarlo por separado.

La señal a vigilar es prop drilling: una prop que se pasa a través de varios componentes puramente para llegar a un consumidor profundamente anidado, con cada componente en el medio pasándola directo sin usarla. Una o dos capas de eso es normal y no vale la pena reestructurar. Cuando se estira a través de muchas capas, o cuando varias ramas no relacionadas del árbol todas necesitan el mismo valor, ese es el momento en que Context o una librería de manejo de estado se justifican. Elevar el estado y pasar props hacia abajo sigue siendo la herramienta correcta para estado compartido entre componentes cercanos; es la herramienta equivocada una vez que el árbol entre ellos se vuelve profundo.

JunoMueve el estado compartido al padre Cuando dos componentes necesitan el mismo valor, el truco es darle el valor a su padre compartido más cercano en lugar de a cualquiera de los componentes. Ese padre mantiene el estado, pasa el valor hacia abajo a ambos, y pasa una función para que un hijo pueda pedir cambios.

El hijo nunca es dueño del valor; usa lo que le dan y le pide al padre que lo actualice.

JunoMueve el estado compartido al padre Eleva el estado al padre común más cercano cuando dos componentes necesitan compartirlo, y pasa el valor y su setter hacia abajo como props, normalmente una prop value y un callback de estilo onChange. Mantén el estado tan local como pueda ser; solo elévalo cuando algo más también lo necesita.

Para cualquier cosa compartida a través de muchos componentes anidados, Context es la herramienta mejor, y el capítulo Context cubre cómo.

JunoMueve el estado compartido al padre Por defecto usa estado colocado y eleva solo hasta el consumidor compartido más cercano, pasando el valor y su setter hacia abajo como props. Mantén una única fuente de verdad por valor en lugar de sincronizar copias entre componentes.

Vigila prop drilling, una prop pasada a través de capas que no la usan, como señal de que Context o un store es mejor opción que elevar más.

Próximo: Effects, donde usarás useEffect para manejar trabajo que ocurre fuera del rendering.