DEV Community

Sebastián Maciel
Sebastián Maciel

Posted on

useState | Entrevistas de React

Lo importante sobre los hooks de react para tener en cuenta en una entrevista, es potencialmente poder saber y responder tres puntos esenciales:

  • Qué son en simples palabras
  • Qué problemas resuelven
  • Un ejemplo simple de implementación

En esta ocasión, nos toca el manejo de estado.


useState

Qué es?

Este hook es básicamente una forma de declarar una variable que para React va a tener un significado especial:

Cada vez que cambiemos el valor de esta variable, React va a detectar esa actualización y disparar un rerender del componente en el que se encuentra. O sea, volver a crear este componente, volver a pintarlo en el navegador.


Qué problema resuelve?

La idea es tener una manera de que React reaccione ante un cambio que realicemos en una variable. Veamos un ejemplo, sin React:

// Inicializamos una variable que vamos a usar de contador:
let counter = 0

// Actualizamos el valor de esa variable de manera típica:
counter++
Enter fullscreen mode Exit fullscreen mode

Con el ejemplo anterior, efectivamente vamos a aumentar el contador. Pero React no va a estar al tanto de ese cambio. Por lo que si usamos esa variable para mostrar algo en el navegador, el cambio no se va a reflejar.

Ahora, usemos useState:

const [ counter, setCounter ] = useState(0)
Enter fullscreen mode Exit fullscreen mode

Para entender lo que pasa, tenemos que tener bien sabidos dos conceptos de JavaScript:


Estos dos conceptos nos dejan entender que useState es básicamente una función que React nos brinda que tiene dos características simples:

  • Es una función que puede tomar como parámetro, una de dos cosas:
    • Un valor que inicializa la variable counter (lo más común)
    • Una función de inicialización (menos común, más sobre esto luego)
  • Y a su vez, nos devuelve un array con dos elementos:
    • La variable con el valor que nos interesa.
    • Una función que sirve para actualizar esa variable.

La forma más simple de usarla es:

setCounter(1)
Enter fullscreen mode Exit fullscreen mode

Esto va a lograr que React vuelva a crear el componente donde estemos usando este hook, y a su vez actualizar el valor de la variable counter a 1.

Veamos un ejemplo de componente real:

import { useState } from "react";

const MyCounter = () => {
  const [counter, setCounter] = useState(0);

  return (
    <>
      <button onClick={() => setCounter(counter + 1)}>Add</button>
      <p>{counter}</p>
    </>
  );
};
Enter fullscreen mode Exit fullscreen mode

Este componente simple cumple con dos tareas:

  • Mostrar un botón que al hacer click ejecuta el setCounter:
    • setCounter recibe el valor actual de counter y lo incrementa.
    • React entiende que hubo un cambio en la UI y dispara un rerender.
  • Un paragraph que muestra el valor de la variable counter.

Casos especiales

Lo interesante de leer las librerías es que vas descubriendo cosas como por ejemplo, que la función setCounter acepta un valor para actualizar counter, pero también se le puede pasar una función.

De esta función podemos recibir un parámetro que es realmente el último valor de counter. Realmente, al inicio de nuestro camino en React es probable que no nos haga mucha diferencia utilizar un método u otro:

<button onClick={() => setCounter(counter + 1)}>
  Add
</button>

// O también

<button onClick={() => setCounter((currentCounter) => currentCounter + 1)}>
  Add
</button>
Enter fullscreen mode Exit fullscreen mode

Solamente cuando nos encontramos utilizando este setCounter en ocasiones o en conjunto con operaciones que lleven un cierto tiempo en completarse, como acciones asíncronas, es cuando necesitamos realmente el último valor actualizado de counter. Son esos detalles que nos vuelven locos y que terminamos entendiendo de una manera u otra. No hay que pretender entender esto en los primeros momentos del proceso de aprendizaje.

La regla es: recordar que nuestro valor está tardando en actualizarse, o que se está actualizando mal debido a que no estamos tomando el último valor realmente disponible.


Función inicializadora

En otros momentos, necesitamos inicializar el primer estado de nuestro useState con algún valor que quizás lleve un tiempo en resolver, como una llamada a un endpoint, algún cálculo matemático o incluso leer algo de localStorage. Algo simple pero que lleve un tiempo.

Es muy poco probable tener que usar esto, realmente. Pero useState también acepta una función que sirve para inicializar solamente una vez y al inicio del renderizado del componente, el valor de nuestro estado. Sería algo así:

const processedUserInfo = getUserComplexInfo()

const [userInfo, setUserInfo] = useState(() => processedUserInfo)
Enter fullscreen mode Exit fullscreen mode

Lo que va a hacer esto es: llenar nuestro userInfo con la información calculada o procesada una sola vez. Pagamos el precio de la tardanza la primera vez y listo. Luego podemos actualizar y rerenderizar el componente todas las veces siguientes, sin tener que volver a procesar la info de getUserComplexInfo.

Normalmente es raro utilizar esto, pero existe por una razón. Como regla es bueno medir la performance de tu componente. Realmente si requiere esta manera de inicializar el estado entonces considerar usarlo. Pero optimizar por el mero hecho de optimizar, puede salir más caro de lo que parece.

Por último: si tu componente tiene muchos useState, es muy probable que necesites usar un useReducer para simplificar el manejo de estado de tu componente. Así vas a ganar practicidad en la lectura del código y evitar la repetición y malas prácticas.


Si te gustó este contenido y estás iniciando o llevás un tiempo en React y te gustaría que escriba sobre algún otro tema en particular, dejame tu comentario.

Voy a seguir atacando estos temas básicos sobre React de todas maneras.

Gracias por el tiempo!

Seba.

Top comments (0)