State management is a critical part of any modern React application, and Redux has been a popular solution for managing the state of large, complex apps. However, traditional Redux often required a lot of boilerplate code, making it harder to set up and maintain. This is where Redux Toolkit (RTK) comes in—it simplifies the Redux workflow and is now the recommended approach for working with Redux in React.
In this article, we’ll walk through how to use Redux Toolkit with React to manage state effectively, using a simple counter app as an example.
What is Redux Toolkit?
Redux Toolkit is an official, opinionated set of tools that simplify common Redux tasks. It provides utilities for:
- Creating Redux slices: Simplifies reducer and action creation.
- Setting up the Redux store: Provides a pre-configured store with best practices.
- Handling async logic: Using
createAsyncThunk
to handle asynchronous actions like API calls.
By using Redux Toolkit, you can reduce the boilerplate and focus more on your application logic.
Setting Up the Project
First, let’s create a new React project and install Redux Toolkit along with React-Redux.
- Create a new React app: bashCopy code
npx create-react-app redux-toolkit-demo cd redux-toolkit-demo
- Install Redux Toolkit and React-Redux: bashCopy code
npm install @reduxjs/toolkit react-redux
Now that the setup is complete, let’s start writing our app.
Example: Simple Counter App with Redux Toolkit
We’ll create a basic counter app where the user can increment and decrement a counter value.
Step 1: Create a Redux Slice
A slice is a collection of Redux logic for a specific feature of your app (like a counter). The createSlice
function from Redux Toolkit automatically generates the actions and reducers for you.
Create a new file called counterSlice.js
in the src
directory:
// src/counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
// Initial state of the counter
const initialState = {
value: 0,
};
// Create a slice of the store
export const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
// Action to increment the counter
increment: (state) => {
state.value += 1;
},
// Action to decrement the counter
decrement: (state) => {
state.value -= 1;
},
},
});
// Export the actions generated by the slice
export const { increment, decrement } = counterSlice.actions;
// Export the reducer to be added to the store
export default counterSlice.reducer;
In this example:
- We define the initial state of the counter (
value: 0
). - We create two reducers:
increment
anddecrement
, which update thevalue
in the state.
Step 2: Configure the Store
Now we need to set up the Redux store and add the counterSlice
reducer to it.
Create a file called store.js
:
// src/store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
// Set up the Redux store
export const store = configureStore({
reducer: {
counter: counterReducer, // Attach the counter slice to the store
},
});
The configureStore
method from Redux Toolkit automatically adds useful middleware like redux-thunk
and sets up Redux DevTools integration.
Step 3: Provide the Redux Store to Your App
In your index.js
file, use the Provider
component from react-redux
to make the Redux store available to the rest of your app.
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import './index.css';
import App from './App';
import { store } from './store';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
Step 4: Create the Counter Component
Now, we can create the React component that will display the counter value and allow the user to increment or decrement it.
// src/App.js
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { increment, decrement } from './counterSlice';
function App() {
// Access the counter value from the Redux store
const counter = useSelector((state) => state.counter.value);
// Get the dispatch function to send actions
const dispatch = useDispatch();
return (
<div className="App">
<h1>Counter: {counter}</h1>
<button onClick={() => dispatch(increment())}>Increment</button>
<button onClick={() => dispatch(decrement())}>Decrement</button>
</div>
);
}
export default App;
In the App.js
file:
useSelector
is used to get the current counter value from the Redux store.useDispatch
is used to get thedispatch
function, which we use to sendincrement
anddecrement
actions to the store.
Conclusion
With Redux Toolkit, managing state in a React app becomes much easier and cleaner. We reduced the boilerplate significantly by using createSlice
for both actions and reducers and configureStore
to set up the store.
In this simple counter app, Redux Toolkit helped us:
- Set up the Redux store with minimal configuration.
- Automatically generate actions and reducers.
- Handle immutable state updates easily.
Redux Toolkit is ideal for larger applications where managing global state becomes complex, and it’s the best way to integrate Redux with React in 2025.