Por qué Redux Toolkit es la forma de usar Redux hoy
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
¿Qué es Redux Toolkit?
Redux Toolkit (también conocido como "RTK") es nuestro enfoque oficial recomendado para escribir lógica Redux. El paquete @reduxjs/toolkit envuelve al núcleo redux e incluye métodos API y dependencias comunes que consideramos esenciales para construir aplicaciones Redux. Redux Toolkit incorpora nuestras mejores prácticas recomendadas, simplifica la mayoría de tareas Redux, previene errores comunes y facilita el desarrollo de aplicaciones Redux.
¡Si estás escribiendo cualquier lógica Redux hoy, deberías estar usando Redux Toolkit para ese código!
RTK incluye utilidades que simplifican casos de uso comunes, como la configuración del store, creación de reducers y lógica de actualización inmutable, e incluso crear "slices" completos de estado de una vez.
Ya seas un usuario nuevo de Redux configurando tu primer proyecto, o un usuario experimentado que quiere simplificar una aplicación existente, Redux Toolkit puede ayudarte a mejorar tu código Redux.
Consulta estas páginas para aprender a usar "Redux moderno" con Redux Toolkit:
- El tutorial "Redux Essentials", que enseña "cómo usar Redux correctamente" con Redux Toolkit para aplicaciones reales.
- Redux Fundamentals, Parte 8: Redux Moderno con Redux Toolkit, que muestra cómo convertir ejemplos básicos anteriores en equivalentes modernos con Redux Toolkit.
- Usando Redux: Migrando a Redux Moderno, que cubre cómo migrar diferentes tipos de lógica Redux heredada a equivalentes modernos.
Cómo difiere Redux Toolkit del núcleo de Redux
¿Qué es "Redux"?
Lo primero es preguntarse: "¿qué es Redux?"
Redux realmente consiste en:
-
Un store único que contiene estado "global"
-
Despachar acciones (objetos planos) al store cuando ocurre algo en la aplicación
-
Funciones reductoras puras que examinan esas acciones y devuelven estado actualizado inmutablmente
Aunque no es obligatorio, tu código Redux normalmente también incluye:
-
Creadores de acciones que generan esos objetos
-
Middleware para habilitar efectos secundarios
-
Funciones thunk que contienen lógica síncrona/asíncrona con efectos secundarios
-
Estado normalizado para buscar elementos por ID
-
Funciones selectoras memoizadas con Reselect para optimizar datos derivados
-
La extensión Redux DevTools para ver historial de acciones y cambios de estado
-
Tipos TypeScript para acciones, estado y otras funciones
Además, Redux normalmente se usa con la biblioteca React-Redux para conectar componentes React al store.
¿Qué hace el núcleo de Redux?
El núcleo de Redux es una biblioteca muy pequeña y deliberadamente sin opiniones. Proporciona primitivas API básicas:
-
createStorepara crear un store Redux -
combineReducerspara combinar múltiples reductores en uno solo -
applyMiddlewarepara combinar múltiples middleware en un store enhancer -
composepara combinar múltiples store enhancers en uno solo
Más allá de esto, toda la lógica relacionada con Redux en tu aplicación debe ser escrita íntegramente por ti.
La buena noticia es que esto permite usar Redux de muchas formas distintas. La mala noticia es que no hay ayudas para facilitar la escritura del código.
Por ejemplo, un reductor es simplemente una función. Antes de Redux Toolkit, típicamente escribirías ese reductor con un switch y actualizaciones manuales. También tendrías creadores de acciones y constantes de tipo escritos a mano:
const ADD_TODO = 'ADD_TODO'
const TODO_TOGGLED = 'TODO_TOGGLED'
export const addTodo = text => ({
type: ADD_TODO,
payload: { text, id: nanoid() }
})
export const todoToggled = id => ({
type: TODO_TOGGLED,
payload: id
})
export const todosReducer = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return state.concat({
id: action.payload.id,
text: action.payload.text,
completed: false
})
case TODO_TOGGLED:
return state.map(todo => {
if (todo.id !== action.payload) return todo
return {
...todo,
completed: !todo.completed
}
})
default:
return state
}
}
Ninguno de estos códigos depende específicamente de API del núcleo redux. Pero es mucho código para escribir. Las actualizaciones inmutables requerían spreads manuales y operaciones de arrays, siendo muy fácil cometer errores y mutar estado accidentalmente (¡siempre la causa #1 de bugs en Redux!). También era común, aunque no obligatorio, distribuir el código de una funcionalidad en múltiples archivos como actions/todos.js, constants/todos.js y reducers/todos.js.
Además, la configuración del store normalmente requería pasos adicionales para añadir middleware común como thunks y habilitar Redux DevTools, aunque son herramientas estándar usadas en casi todas las apps Redux.
¿Qué hace Redux Toolkit?
Aunque estos eran los patrones mostrados originalmente en la documentación de Redux, desafortunadamente requieren código muy verboso y repetitivo. La mayor parte de este boilerplate no es necesario para usar Redux. Además, este código repetitivo creaba más oportunidades para cometer errores.
Creamos Redux Toolkit específicamente para eliminar el "boilerplate" de la lógica Redux escrita a mano, prevenir errores comunes y proporcionar APIs que simplifiquen tareas estándar de Redux.
Redux Toolkit comienza con dos APIs clave que simplifican las acciones más comunes en cualquier app Redux:
-
configureStoreconfigura un store Redux optimizado con una sola llamada, incluyendo combinar reductores, añadir middleware thunk y configurar la integración con Redux DevTools. Además, es más fácil de configurar quecreateStoreporque acepta parámetros con nombre. -
createSlicete permite escribir reductores usando la biblioteca Immer para escribir actualizaciones inmutables con sintaxis JS de "mutación" comostate.value = 123, sin spreads. También genera automáticamente funciones creadoras de acciones para cada reductor y strings de tipo de acción internamente. Finalmente, funciona excelente con TypeScript.
Esto significa que el código que tú escribes puede ser drásticamente más simple. Por ejemplo, ese mismo reductor de tareas podría ser:
import { createSlice } from '@reduxjs/toolkit'
const todosSlice = createSlice({
name: 'todos',
initialState: [],
reducers: {
todoAdded(state, action) {
state.push({
id: action.payload.id,
text: action.payload.text,
completed: false
})
},
todoToggled(state, action) {
const todo = state.find(todo => todo.id === action.payload)
todo.completed = !todo.completed
}
}
})
export const { todoAdded, todoToggled } = todosSlice.actions
export default todosSlice.reducer
Todos los creadores de acciones y tipos se generan automáticamente, y el código del reductor es más corto y fácil de entender. También queda mucho más claro qué se actualiza en cada caso.
Con configureStore, la configuración del store se simplifica a:
import { configureStore } from '@reduxjs/toolkit'
import todosReducer from '../features/todos/todosSlice'
import filtersReducer from '../features/filters/filtersSlice'
export const store = configureStore({
reducer: {
todos: todosReducer,
filters: filtersReducer
}
})
Nota que esta única llamada a configureStore hace automáticamente todo el trabajo de configuración habitual:
-
Los reductores de slice se pasan automáticamente a
combineReducers() -
El middleware
redux-thunkse añade automáticamente -
Se añade middleware de desarrollo para detectar mutaciones accidentales
-
La extensión Redux DevTools se configura automáticamente
-
Los enhancers de middleware y DevTools se componen juntos y se añaden al store
Al mismo tiempo, configureStore permite modificar cualquier comportamiento por defecto (como desactivar thunks para añadir sagas, o deshabilitar DevTools en producción).
Además, Redux Toolkit incluye otras APIs para tareas comunes de Redux:
-
createAsyncThunk: abstrae el patrón estándar de "despachar acciones antes/después de una petición asíncrona" -
createEntityAdapter: reductores predefinidos y selectores para operaciones CRUD en estados normalizados -
createSelector: una reexportación de la API estándar de Reselect para selectores memoizados -
createListenerMiddleware: un middleware de efectos secundarios para ejecutar lógica en respuesta a acciones despachadas
Finalmente, el paquete RTK también incluye "RTK Query", una solución completa para la obtención de datos y caché en aplicaciones Redux, como un punto de entrada opcional separado (@reduxjs/toolkit/query). Te permite definir endpoints (REST, GraphQL o cualquier función asíncrona), y genera un reductor y middleware que gestionan completamente la obtención de datos, actualización del estado de carga y almacenamiento en caché de resultados. También genera automáticamente hooks de React que pueden usarse en componentes para obtener datos, como const { data, isFetching } = useGetPokemonQuery('pikachu')
Cada una de estas APIs es completamente opcional y está diseñada para casos de uso específicos, pudiendo elegir qué APIs utilizar realmente en tu aplicación. Pero todas están altamente recomendadas para ayudar en esas tareas.
¡Ten en cuenta que Redux Toolkit sigue siendo "Redux"! Sigue existiendo un único store, con objetos de acción despachados para actualizaciones, reductores que actualizan el estado de forma inmutable, además de la capacidad de escribir thunks para lógica asíncrona, gestionar estados normalizados, tipar tu código con TypeScript y usar las DevTools. ¡Simplemente hay mucho menos código que tú debes escribir para obtener los mismos resultados!
Por qué queremos que uses Redux Toolkit
Como mantenedores de Redux, nuestra opinión es:
¡Queremos que todos los usuarios de Redux escriban su código con Redux Toolkit, porque simplifica tu código y elimina muchos errores y fallos comunes de Redux!
La "plantilla" y complejidad de los primeros patrones de Redux nunca fueron una parte necesaria de Redux. Esos patrones existieron solo porque:
-
La "Arquitectura Flux" original usaba algunos de esos mismos enfoques
-
La documentación inicial de Redux mostraba elementos como constantes para tipos de acción que permitían separar el código en diferentes archivos por tipo
-
JavaScript es un lenguaje mutable por defecto, y escribir actualizaciones inmutables requería spreads manuales de objetos y actualizaciones de arrays
-
Redux se construyó originalmente en solo unas semanas y se diseñó intencionadamente para ser solo unas pocas primitivas de API
Además, la comunidad de Redux adoptó algunos enfoques específicos que añaden plantilla adicional:
-
Enfatizar el uso del middleware
redux-sagacomo enfoque común para escribir efectos secundarios -
Insistir en escribir manualmente tipos TS para objetos de acción de Redux y crear tipos unión para limitar qué acciones se pueden despachar a nivel de tipo
A lo largo de los años, hemos visto cómo la gente usa realmente Redux en la práctica. Hemos visto cómo la comunidad escribió cientos de librerías adicionales para tareas como generar tipos y creadores de acciones, lógica asíncrona y efectos secundarios, y obtención de datos. También hemos visto los problemas que consistentemente causan dolor a nuestros usuarios, como mutar accidentalmente el estado, escribir docenas de líneas de código solo para hacer una simple actualización de estado, y tener dificultades para rastrear cómo encaja una base de código. Hemos ayudado a miles de usuarios que intentaban aprender y usar Redux y luchaban por entender cómo encajan todas las piezas, confundidos por la cantidad de conceptos y código adicional que tenían que escribir. Sabemos qué problemas enfrentan nuestros usuarios.
¡Diseñamos Redux Toolkit específicamente para resolver esos problemas!
-
Redux Toolkit simplifica la configuración del store a una única llamada de función clara, manteniendo la capacidad de configurar completamente las opciones del store si es necesario
-
Redux Toolkit elimina mutaciones accidentales, que siempre han sido la causa número 1 de errores en Redux
-
Redux Toolkit elimina la necesidad de escribir manualmente creadores de acciones o tipos de acción
-
Redux Toolkit elimina la necesidad de escribir lógica de actualización inmutable manual y propensa a errores
-
Redux Toolkit facilita escribir el código de una funcionalidad Redux en un solo archivo, en lugar de repartirlo en múltiples archivos separados
Redux Toolkit ofrece un excelente soporte para TypeScript, con APIs diseñadas para brindarte máxima seguridad de tipos y minimizar la cantidad de definiciones necesarias en tu código.
RTK Query puede eliminar la necesidad de escribir ningún thunk, reducer, creador de acciones o hook de efectos para gestionar la obtención de datos y el seguimiento del estado de carga.
Debido a esto:
Recomendamos específicamente que nuestros usuarios deben usar Redux Toolkit (el paquete @reduxjs/toolkit), y no deben usar el paquete heredado redux para ningún código nuevo de Redux hoy en día.
Incluso para aplicaciones existentes, recomendamos al menos reemplazar createStore por configureStore, ya que el middleware en modo desarrollo también te ayudará a detectar mutaciones accidentales y errores de serialización en bases de código existentes. También queremos animarte a migrar los reducers que más uses (y cualquier otro que escribas en el futuro) a createSlice: el código será más corto y fácil de entender, y las mejoras de seguridad te ahorrarán tiempo y esfuerzo en el futuro.
El paquete redux aún funciona, pero hoy lo consideramos obsoleto. Todas sus APIs también se reexportan desde @reduxjs/toolkit, y configureStore hace todo lo que createStore hacía pero con mejor comportamiento predeterminado y mayor capacidad de configuración.
Sí es útil entender los conceptos de bajo nivel, para comprender mejor lo que Redux Toolkit hace por ti. Por eso el tutorial "Redux Fundamentals" muestra cómo funciona Redux sin abstracciones. Pero, muestra esos ejemplos únicamente como herramienta de aprendizaje, y finaliza mostrando cómo Redux Toolkit simplifica el código Redux escrito manualmente.
Si estás usando el paquete redux por sí solo, tu código seguirá funcionando. Pero te animamos encarecidamente a cambiar a @reduxjs/toolkit y actualizar tu código para usar las APIs de Redux Toolkit.
Más información
Consulta estas páginas de documentación y publicaciones para más detalles: