# ¿Y si paso un state setter como prop?

Trabajando en React es posible que, bajo los entresijos de algún proyecto, te hayas encontrado componentes que reciben alguna prop como esta:

```javascript
<SomeInputField setValue={setValue} /> // 🤔
```

Si tienes suficiente experiencia en React puede que evites esto sin siquiera pensarlo. No obstante, qué bueno es poder razonarlo para ayudar al equipo a estar en la misma página.

Si por el contrario llevas poco tiempo o ya has cogido el vicio, puede que estés pensando que no es tan malo.

Bueno, yo también he estado ahí. *Let's talk about this.*

## Cuál es el problema

Tal vez sea verdad que hay casos pequeños donde no supone un problema aparente, pero por favor, echa un vistazo a este otro ejemplo:

```javascript
<SomeComponent
  setForm={setForm}
  setCart={setCart}
  setUser={setUser}
  setMeFree={setMeFree}
/>
```

Ahora considera estas preguntas básicas:

* ¿Cuándo cambia cada estado?
    
* ¿Qué o quién los hace cambiar?
    
* ¿Cómo cambian exactamente?
    
* ¿Dónde está el código que lo hace?
    

Como puedes observar, el código no nos da información suficiente para responder a ninguna de las preguntas. Básicamente, no sabemos *nada* de estos estados.

> Pero solo tengo que entrar al código de `SomeComponent`, ¿no? — Alguien dirá

Pues vamos adentro:

```javascript
// En algún lugar de SomeComponent.jsx
<YetAnotherComponent
  setForm={setForm}
  setCart={setCart}
  setUser={setUser}
  setMeFree={setMeFree}
/>
```

¡Vaya! Empieza la frustración. Un bucle al más puro estilo *Inception*, y seguimos sin respuestas.

Es más, los setter pasarán a otros componentes hermanos y seguirán enviándose mediante props a más y más hijos en la jerarquía, multiplicando la cantidad de archivos de código a revisar.

<div data-node-type="callout">
<div data-node-type="callout-emoji">😵‍💫</div>
<div data-node-type="callout-text">No quieres revisar 15 archivos para entender un estado</div>
</div>

¿Ves cuál es el problema? El estado es un elemento clave de la aplicación ¡y así es difícil saber lo que hace!

## Cómo escapar de esto

Volvamos a las preguntas de antes: ¿cuándo cambia el estado? ¿cómo? ¿dónde?... ¿No sería genial poder responderlas sin tener que ir a otros archivos?

Atentos, porque hay una forma y es estándar. Y si existe un estándar es porque presenta ventajas frente a otros métodos.

Seguir estándares suele ahorrar muchos problemas.

### Fíjate en el código nativo

Definitivamente no hay ninguna prop estándar con nombre de setter.

> Un `input` no recibe `setValue`

¿Lo has visto en componentes nativos? ¿kits de UI? ¿librerías populares? Nada.

Lo que sí habrás visto es esto:

```javascript
<input onChange={...} /> // 👀
```

Así es, un input nativo no ofrece una prop `setValue`, sino una prop `onChange`.

Esta prop de evento espera una función, donde típicamente se usa el contenido del argumento `event` para hacer una actualización de estado:

```javascript
<input onChange={
  event => setValue(event.target.value)
} />
```

Piensa en la información tan valiosa que tenemos aquí:

* El nombre de la prop ya te da una idea de cuándo sucede
    
* Es fácil imaginar la acción responsable del cambio
    
* Se ve exactamente cómo cambia el estado
    
* Todo el código relevante está a la vista
    

¿No es genial?

### La clave: división de responsabilidad

Vamos a señalar el motivo por el que esto funciona tan bien.

<div data-node-type="callout">
<div data-node-type="callout-emoji">👉</div>
<div data-node-type="callout-text">Hay división de responsabilidad</div>
</div>

Cuando hay división de responsabilidad, cada pieza del sistema tiene un propósito bien definido y delimitado. A menudo se puede entender por sí misma sin acudir al resto.

Esto es importante en esta profesión, porque cuanto menos tiempo tardes en entender, antes podrás empezar a tocar.

Siguiendo con la división de responsabilidad: el `input` nativo no quiere saber nada de cómo se cambia tu estado, eso es problema de tu componente padre.

El `input` solo te habla de lo que él controla gracias a la event prop `onChange`:

* Cuándo ocurre un cambio
    
* Los detalles de ese cambio
    

Así que, en vez de enviar un *state setter* como prop, ha llegado el momento de imitar el patrón nativo: las *event props*.

### Hazlo en tus componentes

El estado y sus valores son responsabilidad única del componente que declara el `useState`. Por ejemplo, si tuvieras un componente que gestiona una lista:

```javascript
// List.jsx
const [list, setList] = useState([])
```

Digamos que vamos a tener un hijo `Item` con la capacidad de borrarse del listado.

El padre `List` es responsable de hacer cada `setList` en su propio código. No delegará esa responsabilidad en `Item`:

```javascript
// También en List.jsx
const handleRemoveItem = id => setList(list.filter(...))
return <Item onRemove={handleRemoveItem} />
```

`Item` no debe saber nada sobre la lista completa del padre ni cómo ha de cambiar, pero hay dos cosas que sí son su responsabilidad:

* Cuándo se ha de borrar: porque tendrá un botón para hacerlo
    
* Cuál se ha de borrar: porque sabrá su propio id
    

Como ya hemos visto, en lugar de recibir `setList` directamente vamos a exponer una *event prop* que permita al padre estar al tanto de estas cosas:

```javascript
function Item ({ onRemove }) {
  const myId = 27
  return <button onClick={() => onRemove(myId)}>❌</button>
}
```

Pero `Item` nunca decidirá qué hacer con un estado que no es suyo, y de hecho desde su código no tendrá acceso explícito a ningún setter ajeno.

Ya está, cada componente tiene su responsabilidad y ninguno invade la del otro. Vamos a mirar el código completo de `List` una última vez:

```javascript
// ✅
function List () {
  const [list, setList] = useState([])
  const handleRemoveItem = id => setList(list.filter(...))
  return <Item onRemove={handleRemoveItem} />
}
```

Todas las preguntas sobre el estado tienen respuesta sin salir del archivo:

* ¿Cuándo cambia el estado? — Al suceder la acción "borrar"
    
* ¿Qué o quién lo hace cambiar? — El usuario que interactúa con `Item`
    
* ¿Cómo cambia exactamente? — Con un `.filter()`, está a la vista
    
* ¿Dónde está el código que lo hace? — En el mismo archivo
    

Pero, solo por saborear una vez más la diferencia:

```javascript
// ❌
function List () {
  const [list, setList] = useState([])
  return <Item setList={setList} />
}
```

En contraste, aquí ya no tendríamos ni idea de cuándo, dónde, cómo o qué se está haciendo con el estado.

## Conclusión

<div data-node-type="callout">
<div data-node-type="callout-emoji">⚡</div>
<div data-node-type="callout-text">Si imitamos el modelo nativo recibimos <em>event props</em>, no <em>state setters</em></div>
</div>

❌ Pasar *state setters* como props oscurece la lógica de estado fragmentándola en diferentes archivos, lo que resulta en dificultades para entenderla.

```javascript
const [value, setValue] = useState('')
<SomeInputField setValue={setValue} /> // ???
```

✅ El estándar nativo de las *event props* ayuda a delimitar correctamente la responsabilidad del estado y sus cambios junto al código donde se declara el estado.

```javascript
const [value, setValue] = useState('')
<AwesomeInputField onChange={next => setValue(next)} />
```
