How Redux Has Changed and Why It's Still Added to New Projects
Remember the times when a simple Redux counter required creating three separate files, declaring a dozen constants, and writing a huge switch-case in the reducer? Because of this, thousands of developers came to hate the library. But Redux is no longer what it was in 2015.
The developers recognized the problem in time and released Redux Toolkit (RTK). Today it has become the standard for working with the library and removed almost everything that Redux was previously criticized for.
Why Do You Even Need a Global State Manager
In small React applications, you can easily get by with regular prop passing or built-in React Context. Problems start when the project grows. When data from one form needs to simultaneously update a sidebar, the site header, and send analytics, the prop chain turns into chaos.
Redux keeps the application state in one object (store). You don't change this object directly. Instead, you dispatch an action, and pure functions, reducers, compute the new state based on the old one.
This approach gives clear predictability. If something breaks in the application, through Redux DevTools you can view the full history of state changes and rewind time, tracking user actions step by step.
How Redux Toolkit Made Life Easier
Previously, to update a single field you had to manually track object immutability, creating cumbersome spreads.
Redux Toolkit has Immer built in. Now code inside reducers is written as if you're mutating state directly, and the library automatically converts this into a safe immutable update.
Let's look at a basic counter example:
import { createSlice, configureStore } from '@reduxjs/toolkit'
const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0
},
reducers: {
incremented: state => {
// Immer улавливает "мутацию" и создает новое состояние
state.value += 1
},
decremented: state => {
state.value -= 1
}
}
})
export const { incremented, decremented } = counterSlice.actions
const store = configureStore({
reducer: counterSlice.reducer
})
store.subscribe(() => console.log(store.getState()))
store.dispatch(incremented()) // { value: 1 }
store.dispatch(incremented()) // { value: 2 }
store.dispatch(decremented()) // { value: 1 }
No separate files with action types. The createSlice function created both the reducer and action generators for you.
When Redux Is Needed and When It's Better to Do Without It
The library's creator Dan Abramov wrote "You Might Not Need Redux" years ago. This advice is still relevant today.
Redux comes in handy in specific situations:
- There's a lot of data that actively changes over time and is used in different parts of the application.
- The state update logic is complex or requires strict sequencing.
- Convenient debugging with a transparent history of all events is needed.
- Many people work on the team, and a single clear data handling pattern is required.
If you have a simple application where data just needs to be passed a couple levels down, pulling in Redux here isn't worth it. Extra abstractions will only complicate the code.
Quick Start
The easiest way to spin up a project is with Vite and a ready-made Redux Toolkit and TypeScript template:
npx degit reduxjs/redux-templates/packages/vite-template-redux my-app
For Next.js, there's a ready-made template from Vercel:
npx create-next-app --example with-redux my-app
If you're adding the library to an existing project, it's enough to install two packages:
npm install @reduxjs/toolkit react-redux
The Bottom Line
The Redux core weighs about 2 KB. The library has long moved past the era of endless boilerplate code. Paired with Redux Toolkit, you get a strict and predictable tool for state management that works great in large projects.
相关项目