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

Elevar el estado

Un campo de texto está al lado de una vista previa que necesita mostrar lo que se haya 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 contiene. La solución es mover ese estado hacia el componente padre más cercano que ambos comparten, y luego pasar el valor hacia abajo a cada uno como prop. Esto se llama elevar el estado.

Aquí 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 hacia abajo a ambos, y pasa setText hacia abajo 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 ningún estado propio.

Mantén el estado lo más bajo posible

Elevar el estado es una maniobra que haces solo cuando la necesitas. La regla guía es la colocación de estado: mantén cada pieza de estado lo más bajo en el árbol que pueda estar, cerca del componente que realmente la usa, y elévala solo cuando algo más necesita leerla o cambiarla también. Un componente con estado que nadie más toca debe mantener ese estado para sí mismo.

Esto importa porque elevar tiene un costo. Cada nivel que una pieza de estado sube, el padre tiene que pasarla hacia abajo de nuevo como prop, y cada componente en el medio tiene que aceptar y reenviar esa prop incluso si nunca usa el valor. Empieza en lo local. Sube el estado solo hasta el componente más cercano que realmente necesita compartirlo, no más lejos.

Pasar el setter hacia abajo

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

Para estado que se comparte entre componentes anidados muchos niveles aparte, 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 el capítulo Hooks cubre useContext, el hook que lee un valor sin llevarlo a través de cada componente en el medio. Eso está fuera del alcance de este capítulo; el patrón de arriba es el que debes usar primero.

Elige un componente para que sea dueño de una pieza de estado dada y trátalo como la fuente única de verdad para ese valor. No dejes que un segundo componente tenga una copia del mismo dato en su propio estado e intente mantener los dos sincronizados a mano. 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 extras que te habría costado elevar el estado en primer lugar. Si un valor puede derivarse de estado que ya existe en algún lugar, derívalo durante el render en lugar de almacenarlo por separado.

La señal a observar es el prop drilling: una prop que se pasa a través de varios componentes simplemente para alcanzar un consumidor profundamente anidado, con cada componente en el medio pasándola directamente y nunca usándola. Una o dos capas de eso es normal y no vale la pena reestructurar. Cuando se extiende a través de muchas capas, o cuando varias ramas no relacionadas del árbol todas necesitan el mismo valor, es cuando Context o una librería de gestión de estado vale la pena. Elevar el estado y pasar props hacia abajo sigue siendo la herramienta correcta para estado compartido por componentes que están cerca; 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 común más cercano en lugar de a cualquiera de los dos componentes. Ese padre mantiene el estado, pasa el valor hacia abajo a ambos, y pasa hacia abajo una función para que un hijo pueda solicitar 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 de valor y un callback al estilo onChange. Mantén el estado tan local como pueda serlo de otra forma; solo eleva cuando algo más lo necesita también. Para cualquier cosa compartida a través de muchos componentes anidados, Context es la herramienta mejor, y el capítulo de Hooks cubre cómo hacerlo.
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 fuente única de verdad por valor en lugar de sincronizar copias entre componentes. Observa el prop drilling, una prop pasada a través de capas que no la usan, como la señal de que Context o un store son el mejor ajuste en lugar de elevar más.

Siguiente: Effects, donde usarás useEffect para manejar trabajo que sucede fuera del renderizado.