React UseState básico

Antes de la aparición de los hooks en React la única forma de tener estado era usando componentes de clases o tirando de soluciones tales como redux.

Desde que aparecieron los hooks podemos usar el hook useState para tener estado en componentes funcionales.

¿Por qué?

¿Por qué no puedo usar una variable para almacenar la información? Si vienes de tecnologías de backend, o de frameworks como angular, estarás acostumbrado a poner variables miembro en tu clase y tirar para adelante, esto no es posible en un componente funcional.

Veamos porque:

Partimos de un codesandbox en el que tenemos un proyecto básico de React creado.

Vamos a crear un componente simple en el que mostraremos un nombre y dejaremos al usuario que pueda editarlo:

export default function App() {
  return (
    <div className="App">
      <h1>Hello</h1>
      <input />
    </div>
  );
}

Empezemos a jugar, ¿qué pasaría si usaramos una variable para mostrar y almacenar el nombre que estamos editando?:

export default function App() {
+ // ¡¡ ESTO ESTA MAL !!
+ let myname = "Pepe";

  return (
    <div className="App">
-      <h1>Hello</h1>
+      <h1>Hello {myname}</h1>
-      <input/>
+      <input value={myname} onChange={e => myname = e.target.value}/>
    </div>
  );
}

Si intentamos teclear veremos que esto no funciona, siempre nos mostrará "pepe" como valor, es decir el nuevo valor jamas llegará a guardarse, esto se debe a que:

  • Estamos en un componente función.
  • Este componente función se invoca en cuanto hace falta repintarlo, es decir se vuelve a invocar a la función, se crea la variable que hay dentro de la función,se pinta lo que haya en el return de la misma, y la invocación a la función "muere".
  • Si hace falta repintar el componente volverá a asignar el valor inicial a la variable myname.

¿Cómo podemos añadir estado en un componente funcional? React nos expone el hook useState este hook guarda el valor actual en un sitio seguro que no se eliminará cuando la invocación de la función termine su ejecución. Veamos como:

  • Primero con UseState nos da un array (hacemos destructuring) con una variable que guarda el valor actual, y un dispatcher para poder cambiarlo (si pensáramos en componentes de clase podíamos pensar que esto es como getter y un setter).

  • Después lo usamos en el input por un lado en el atributo value le pasamos la variable, y en el onChange usamos el setMyName para actualizarlo.

import "./styles.css";
+ import React from 'react';

export default function App() {
-  let myname = "Pepe";
+  const [myname, setMyname] = React.useState('Pepe');

  return (
    <div className="App">
      <h1>Hello {myname}</h1>
-      <input value={myname} onChange={e => myname = e.target.value}/>
+     <input value={myname} onChange={e => setMyname(e.target.value)}/>
    </div>
  );
}

Ventana aplicación funcionando correctamente podemos poner el nombre y se actualiza

¿Cómo funciona esta magia negra? La primera vez que se va a ejecutar la función se le asigna un trozo de memoria en la parte de estado fuera de la función, en el momento que hacemos un setState se actualiza esa zona de memoria.

Cuando se vuelve a invocar a la función, setState mira si hay algún valor para ese hook y en caso de que lo tenga se lo asigna.

¿Y cómo sabe que trozo de memoria tiene que asignar al useState que toque? Lo enlaza por componente y línea de código, por esa razón no está permitido invocar a un hook dentro de un if o en una funcióna anidada.

¿Te apuntas a nuestro máster?

Si te ha gustado este ejemplo y tienes ganas de aprender Front End guiado por un grupo de profesionales ¿Por qué no te apuntas a nuestro Máster Front End Online Lemoncode? Tenemos tanto edición de convocatoria con clases en vivo, como edición continua con mentorización, para que puedas ir a tu ritmo y aprender mucho.