Manejo del estado en React con Redux Toolkit

Prometeo
8 min readJul 13, 2022

En la actualidad, los sitios web involucran cada vez más flujos complejos en los cuales se debe pasar información entre distintas pantallas y en los cuales los componentes que conforman las páginas deben reaccionar de acuerdo al cambio de esta información.

Existen distintas herramientas que nos facilitan el manejo del estado cuando la complejidad del sitio web que estamos desarrollando aumenta considerablemente. Una de las más populares y que se acopla perfectamente con React es Redux Toolkit.

Redux Toolkit

Redux Toolkit es un conjunto de herramientas oficial desarrollado por el mismo equipo encargado del Redux original. Trae varias ventajas respecto al Redux original:

  • Es más fácil de utilizar: Incluye diversas utilidades que simplifican los casos de uso más comunes.
  • Es más fácil de implementar: Si has utilizado el Redux tradicional, sabes que incluso para la acción más sencilla se deben crear varios archivos y código boilerplate. Con Redux Toolkit, la cantidad de código necesario para realizar una acción que mute el estado se reduce de manera considerable.
  • Viene integrado con Redux DevTools: De manera que podemos visualizar como el estado de nuestra aplicación va cambiando con cada acción que realizamos y nos facilita el debug de la misma.

A continuación, veremos cómo aplicar Redux Toolkit en un pequeño proyecto de demostración.

Proyecto de usuarios y tareas

Crearemos un proyecto simple en el que podremos visualizar una lista de usuarios, las tareas que tienen asignadas y el estatus de estas. Utilizaremos el API de to-dos y users de https://jsonplaceholder.typicode.com para obtener los datos dummy que usaremos en el proyecto.

Redux Toolkit tiene una plantilla de create-react-app que ya contiene las librerías para poder utilizarlo directamente. Para crear un proyecto nuevo con esa plantilla, ejecutamos el siguiente comando:

npx create-react-app my-app — template redux

Instalamos también react-router-dom para poder manejar el ruteo de la aplicación con el siguiente comando:

yarn add react-router-dom

Borramos algunos de los archivos y carpetas que vienen con la plantilla que no serán necesarios para este proyecto de modo que quede de la siguiente manera:

Reemplazamos el contenido del archivo index.css por el siguiente

Ahora reemplazaremos el contenido del archivo App.js por el siguiente

En este archivo hemos creado 3 rutas:

  • ‘/’: Será utilizada para acceder a la pantalla principal
  • ‘users’: Será utilizada para acceder a la pantalla con la lista de usuarios
  • /users/:id’: Será utilizada para acceder a la pantalla con los detalles de un usuario en específico

Reemplazamos el contenido del archivo index.js por el siguiente

Aquí estamos usando configureStore, una función propia de Redux Toolkit, que nos permite configurar nuestro state store a través de un reducer único que combina todos los reducers individuales que podamos tener en nuestro proyecto.

Slices

En vez de tener que manejar archivos separados para los reducers, las actions, etc como en el Redux tradicional, en Redux Toolkit se utilizan slices. Un slice está normalmente conformado por 3 partes:

  • La declaración del estado inicial: Donde se asignan los valores iniciales que tendrán las distintas variables del slice.
  • Los reducers: Funciones que pueden o no recibir parámetros, cuya función es modificar el estado de una o más de las variables declaradas en el estado inicial. En Redux Toolkit se utiliza la función createSlice para combinar el estado inicial con los reducers.
  • Las funciones agrupadoras: Esta parte no es obligatoria de incluir en un slice, pero usualmente se utiliza para agrupar el llamado a varios reducers en una sola función, por ejemplo, en casos en los que se llama a un API y dependiendo si el resultado fue exitoso o no se deben alterar distintas partes del estado.

Un slice genera automáticamente los action types y los action creators y exporta el selector, que es lo que nos permite acceder a los distintos atributos del estado en los componentes. Al generar lo mencionado anteriormente de manera automática, nos evitamos tener que crear otros archivos para declararlos como con el Redux tradicional, con Redux Toolkit el slice es el único archivo necesario. Normalmente se crea un slice por cada unidad lógica de la aplicación.

Para el caso de esta aplicación de prueba, se podrán visualizar a los usuarios tanto en una lista como de manera individual, así como también una lista de las tareas que tienen asignadas, por lo tanto, crearemos 3 slices: uno para la lista de usuarios, uno para el usuario individual y uno para la lista de tareas. Para ello creamos una carpeta slices dentro de src. Dentro de la carpeta slices creamos un archivo llamado users.js e insertamos el siguiente código

En este caso estamos declarando 3 variables en el estado inicial:

  • loading: Con un valor inicial de false
  • hasErrors: Con un valor inicial de false
  • users: Con una lista vacía como valor inicial

Luego estamos definiendo 3 reducers:

  • getUsers: Se ejecutará al momento de llamar a la API y seteará el valor de loading a true, para que por ejemplo la pantalla correspondiente sepa que se debe mostrar un loading spinner o un mensaje de carga mientras se espera por la respuesta del API.
  • getUsersSuccess: Se ejecutará al recibir una respuesta exitosa del API. La lista de usuarios que viene como respuesta del API se guardará en la variable users, mientras que loading se seteará en false y hasErrors también ya que no se obtuvo ningún error.
  • getUsersFailure: Se ejecutará al recibir una respuesta fallida del API, en este caso loading se seteará en false y hasErrors en true, para que la pantalla correspondiente sepa que se debe mostrar un mensaje de error indicándole al usuario que hubo un problema al tratar de obtener los datos.

Finalmente estamos definiendo la función fetchUsers, que como se puede apreciar agrupa los 3 reducers definidos anteriormente.

Creamos otro slice llamado user.js con el siguiente código

Este slice contiene el código para manejar el estado de un usuario específico.

Finalmente creamos un slice llamado tasks.js con el siguiente código

Este slice contiene el código para manejar el estado relacionado a las tareas de un usuario individual.

Ahora que ya tenemos los slices de las distintas entidades, lo que queda es crear el root reducer (el cual pasamos como parámetro en pasos anteriores al método configureStore). Para ello creamos un archivo index.js dentro de la carpeta slices y colocamos el siguiente código

En este archivo estamos utilizando la función combineReducers de Redux para combinar el usersReducer, el tasksReducer y el userReducer en el root reducer.

Ya tenemos todo lo relacionado al estado listo, ahora pasaremos a la creación de los componentes.

Crearemos 3 componentes:

  • Navbar: Tendrá los links a las distintas pantallas de la aplicación
  • Task: Mostrará el título de la tarea y el estatus de esta.
  • User: Mostrará el nombre, nombre de usuario y email de un usuario.

Creamos una carpeta llamada components dentro de src y en ella creamos los archivos antes mencionados.

Este el código para el archivo Navbar.js

Este el código para el archivo Task.js

Este el código para el archivo User.js

Para terminar, solo nos falta crear las pantallas de nuestra aplicación. Crearemos 3 pantallas:

  • Home: Será la página principal de nuestra aplicación.
  • Users: Mostrará una lista de todos los usuarios y sus datos.
  • SingleUser: Mostrará los datos de un usuario en particular, así como también las tareas que tiene asignadas y los datos de estas.

Creamos una carpeta llamada pages y en ella creamos un archivo Home.js con el siguiente código

Creamos un archivo llamado Users.js e insertamos el siguiente código

En este archivo estamos importando la función agrupadora fetchUsers que definimos anteriormente y el usersSelector. Utilizando la función useSelector de Redux estamos sacando del userSelector los atributos users, loading y hasErrors, para en base a su contenido mostrar dinámicamente distintos componentes en la página. La función fetchUsers se está colocando dentro de useEffect, de modo que al cargar la página se llame a esta función.

Finalmente creamos un archivo SingleUser.js y insertamos el siguiente código

En este caso ya que mostraremos tanto al usuario individual como a sus tareas estamos utilizando tanto fetchTasks como fetchUser dentro de useEffect y de la misma manera estamos utilizando la función useSelector con el userSelector y con el tasksSelector para extraer sus atributos.

A probar el proyecto

Como mencionamos al inicio, Redux Toolkit ya viene integrado por defecto con Redux DevTools, lo que nos facilitará ver el estado de la aplicación en un momento determinado, así como también cómo este se ve afectado con nuestras acciones en el sitio web. Para poder utilizarlo debemos instalar en el navegador la extensión de Redux DevTools. Una vez instalado, podemos ejecutar el proyecto con el siguiente comando:

yarn start

Nuestra pantalla principal se ve de la siguiente manera.

Si abrimos el panel de Redux DevTools podemos visualizar el estado inicial de nuestra aplicación.

Como se puede apreciar, los valores de los atributos de los 3 reducers son iguales a los valores que definimos en los slices como el estado inicial.

Si le damos click al tab de Usuarios en el navbar se nos mostrará la pantalla de usuarios.

Volviendo al panel de Redux DevTools, se puede apreciar que ahora el atributo users del reducer de los usuarios tiene 9 usuarios traídos del api.

Para terminar, podemos dar click al botón “ver usuario” de cualquiera de los usuarios. Ahora se nos muestra una pantalla con los datos del usuario y con su lista de tareas con la información correspondiente.

De vuelta al panel de Redux DevTools, vemos ahora que el atributo tasks del reducer de tasks contiene las tareas del usuario traídas del API y el atributo user del reducer de user contiene los datos del usuario seleccionado.

¡Terminamos!

Con este ejercicio hemos visto los beneficios de utilizar Redux Toolkit para manejar el estado en una aplicación de React.

Puedes encontrar el código completo de este ejercicio en el siguiente link: https://github.com/Carlosmave/SampleReduxToolkitProject.

--

--

Prometeo

El presente financiero es abierto y conectado. En Prometeo lo estamos construyendo.