
Mira el video si prefieres:
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
.
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

¿Qué son las Future Flags?
Checa este otro Post
