cover

Introducción a Redux-Toolkit

author photo

Héctorbliss

@hectorbliss


Mira el video si prefieres:

robot logo saying hello

No te quedes atrás: Actualízate

Suscríbete para recibir información sobre nuevos frameworks, updates, eventos, tips, hacks y más.

Redux-Toolkit es la forma más moderna de trabajar con Redux hoy en día. Además de que ahora es más fácil implementar Redux que antes.

Por eso, y para refrescarnos la memoria, si ya has trabajado con versiones anteriores de Redux, vamos a aprender cómo utilizar Redux-Toolkit en esta pequeña serie de 2 entradas. Comencemos con instalarlo todo y aprendamos a usarlo fácilmente. ⚡️

😎 Creando el nuevo proyecto e Instalando dependencias

Vamos a crear un nuevo proyecto React con Vite para poder instalar Redux-Toolkit y configurar todo desde cero.

npx create-vite cd rtk

Llamaremos al proyecto: rtk, seleccionaremos React y el lenguaje de tu preferencia, yo seleccionaré TypeScript. Ahora instalemos las dos herramientas que necesitamos para implementar Redux en este nuevo proyecto.

npm i @reduxjs/toolkit react-redux && npm i

De paso, instalamos todas las dependencias.

📦 Features folder y tu primer slice

Abrimos nuestro proyecto en tu editor de código favorito y creamos una carpeta llamada features dentro de la carpeta src. Para luego crear nuestro primer archivo de Redux: counter-slice.ts. Para este ejemplo, vamos a reutilizar el componente que Vite ya nos regala y que tiene un counter, por eso vamos a crear un “counter-slice”.

// src/features/counter-slice.ts // importamos createSlice para crear nuestro primer slice import { createSlice, PayloadAction } from "@reduxjs/toolkit"; // Declaramos el tipo de nuestra data, en este caso solo necesitamos un valor númerico. type CounterState = { value: number; }; // Declaramos un estado inicial, de preferencia. const initialState: CounterState = { value: 0, }; // Aquí está la mágia, este es nuestro slice. const counterSlice = createSlice({ name: "counter", // El nombre de nuesto slice initialState, // El estado inicial reducers: { // Todos los reducers, que también se convertirán en acciones increment(state) { state.value++; }, }, }); export const { increment } = counterSlice.actions; // Exportamos los métodos de las acciones // Y exportamos el reducer como default de este archivo. export default counterSlice.reducer;

En este tutorial, lo haremos todo con tipado seguro utilizando TypeScript, para lograr un end-to-end type safety. Por eso hemos importado PayloadAction también (lo usaremos más adelante). ✅

⛺️ Ahora vamos a configurar el store

Una vez que tenemos nuestro primer slice: podemos configurar el store, pues el único requisito para crearlo, es justamente, tener un primer reducer. Así que vamos a crear un archivo para nuestra configuración del store en: src/store.ts.

// Importamos la herramienta para crear el store y nuestro primer reducer. import { configureStore } from "@reduxjs/toolkit"; import counterReducer from "./features/counter-slice"; // Creamos el store con configureStore. const store = configureStore({ reducer: { counter: counterReducer }, // Ahora los reducers se combinan automáticamente. }); // Explotaremos el tipado que Redux Toolkit nos regala. export type AppDispatch = typeof store.dispatch; export type RootState = ReturnType<typeof store.getState>; // Exportamos store como default (o como prefieras) export default store;

Una vez más, declaramos tipos y los exportamos para usarlos más adelante.

🔌 Es momento de conectarlo todo

Vamos a nuestro archivo principal main.tsx, donde usamos ReactDOM y agregamos el <Provider> de react-redux; proporcionamos el store.

import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App.tsx"; import "./index.css"; // Importamos tanto el provider como el store import { Provider } from "react-redux"; import store from "./store"; ReactDOM.createRoot(document.getElementById("root")!).render( <React.StrictMode> <Provider store={store}> <App /> </Provider> </React.StrictMode> );

🔬 Estamos listos para probar con las Redux Dev Tools

Para hacer la prueba de nuestra configuración, vamos a instalar las herramientas de desarrollo de Redux. Una forma simple de hacerlo es instalar el plugin para el navegador Chrome.

Una vez instalado, abriremos el inspector (chrome dev tools) y ejecutamos nuestra aplicación con npm run dev.

redux dev tools

Podremos ver que nuestro estado counter ¡está listo! 🤩

🛸 Es hora de usar los Hooks de RTK

Hemos visto cuál es la forma moderna de configurar Redux en nuestro proyecto; es momento de utilizar los Hooks que RTK nos regala: useDispatch y useSelector, pero vamos a tiparlos correctamente para sacarle el máximo provecho a TypeScript. 🤓

// src/hooks.ts // Importamos los conocidos useDispatch y useSelector, además de un tipo import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux"; import { RootState, AppDispatch } from "./store"; // Observa cómo estamos re-declarando los hooks, incluyendo los tipos en los generics, esto generará en automático los nuevos hooks tipados 🤯 export const useAppDispatch = () => useDispatch<AppDispatch>(); export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

Hemos escrito esta configuración para nuestros Hooks en un archivo llamado hooks.ts dentro de src. Pareciera que este paso está de más, pero no es así, pues estás a punto de presenciar la magia 🎩 de Redux + TypeSciript.

🪄 Por fin, usaremos Redux en nuestro componente <App>

Ahora sí, todo está en su lugar, incluida la magia, 🪄 así que vamos a utilizar nuestro estado global para sustituir el contador local que ha creado Vite en el archivo App.tsx.

import reactLogo from "./assets/react.svg"; import viteLogo from "/vite.svg"; import "./App.css"; // Importamos los Hooks que ha generado Redux por nosotros (estos hooks incluyen los tipos) import { useAppDispatch, useAppSelector } from "./hooks"; // También importamos nuestra accion import { increment } from "./features/counter-slice"; function App() { // Sustituimos el estado local por el de Redux const count = useAppSelector((state) => state.counter.value); const dispatch = useAppDispatch(); return ( <> <div> <a href="https://vitejs.dev" target="_blank"> <img src={viteLogo} className="logo" alt="Vite logo" /> </a> <a href="https://react.dev" target="_blank"> <img src={reactLogo} className="logo react" alt="React logo" /> </a> </div> <h1>Vite + React</h1> <div className="card"> {/* Usamos dispatch pasando directamente la invación de increment */} <button onClick={() => dispatch(increment())}>count is {count}</button> <p> Edit <code>src/App.tsx</code> and save to test HMR </p> </div> <p className="read-the-docs"> Click on the Vite and React logos to learn more </p> </> ); } export default App;

Si pones tu mouse encima de la constante count o de dispatch, te darás cuenta de que el tipo es el correcto, gracias a TS. 🥳

👀 Hora de viajar en el tiempo. Recuerda que con las Redux Dev Tools, puedes jugar con la linea del tiempo, rebobinando las acciones para mirar cómo va cambiando el estado.

👯‍♀️ Vamos a agregar una segunda acción

Ahora que podemos usar nuestras acciones y el estado global en nuestros componentes, vamos a agregar una acción, solo para experimentar y familiarizarnos aún más con esta forma de trabajar. Y de paso, haremos uso del payload en el reducer.

// extra action // ... const counterslice = createSlice({ name: "counter", initialState, reducers: { increment(state){ state.vale++; // Gracias a immer, esto es inmutable }, // Aquí es donde usamos el tipo pasando el generic del tipo de dato esperado addAmount(state, action: PayloadAction<number>) { state.value += action.payload; }, } }); // ... export const { incremented, addAmount } = conterSlice.actions;

Ahora que hemos exportado nuestra nueva acción, vamos a usarla en el componente <App>.

// App.tsx import { increment, addAmount } from "./features/counter-slice"; // ... const handleClick = ()=>{ dispatch(amountAded(3)); } // ... <button onClick={() => dispatch(increment())}>count is {count}</button> <br /> <input type="number" onChange={(e) => dispatch(addAmount(Number(e.target.value)))} /> // ...

Si hacemos la prueba ahora, veremos que nuestra acción se ejecuta correctamente. 🥳

¡Ya tienes todo listo para que tus aplicaciones React trabajen con Redux Toolkit!

Lo haz hecho muy bien, yo creo que ya estás listo(a) para que agreguemos asincronía y cache con Redux Query, ¿no te parece? Bueno, pues no te pierdas la siguiente entrada, en la que usaremos este proyecto nuevamente, y agregaremos Redux Query para consumir una API de servidor.

Abrazo. Bliss. 🤓

Enlaces relacionados

Redux Dev tools

banner

¿Quieres mantenerte al día sobre los próximos cursos y eventos?

Suscríbete a nuestro newsletter

Jamás te enviaremos spam, nunca compartiremos tus datos y puedes cancelar tu suscripción en cualquier momento 😉

robot logo saying hello
facebook icontwitter iconlinkedin iconinstagram iconyoutube icon

© 2016 - 2023 Fixtergeek