DEV Community

Cover image for Mastering Redux Toolkit: The Modern Way to Manage State in React
Chinedu Oputa
Chinedu Oputa

Posted on

Mastering Redux Toolkit: The Modern Way to Manage State in React

Introduction

Redux is a global state manager that allows you to manage your app state in a single place, which can be very useful. Redux has long been a cornerstone for state management in React applications, but it’s no secret that the original Redux setup was often too verbose and hard to learn. Developers had to write a lot of boilerplate just to do simple things like updating a counter or fetching data from an API.
Then came Redux Toolkit (RTK) — the official, recommended way to write Redux code.

RTK simplifies Redux development by providing powerful utilities that make state management easier, faster, and less error-prone.
In this guide, we’ll explore what Redux Toolkit is, why it matters, and how to use it effectively — with practical examples you can drop straight into your next React project.

What is Redux Toolkit?

Redux Toolkit (RTK) is the official, opinionated, batteries-included toolset for efficient Redux development.
It was created by the Redux team to solve the biggest issues developers had with Redux: excessive boilerplate, complex store configuration, and too many added packages.
RTK provides:

  • A simplified store configuration.
  • Built-in reducers and immutable updates using Immer.
  • Easy action creation.
  • Integrated middleware for async logic (like redux-thunk).
  • DevTools support and production-ready defaults out of the box.

In a nutshell, Redux Toolkit is an easier and modern way to implement the power of Redux as a global state manager. RTK lets you write less code, avoid common bugs, and get better performance — all while keeping the predictability of Redux.

Redux Toolkit itself is a single package, @reduxjs/toolkit. However, it is designed to be "batteries-included"; consequently, when you install it, you install the following integrated libraries:

  1. Redux core: Redux Toolkit builds on top of the core Redux library, so it's a fundamental part of the toolkit.
  2. Immer: This library simplifies immutable state updates, which is crucial for Redux. Redux Toolkit leverages Immer internally, particularly with createSlice.
  3. Redux Thunk: This middleware enables handling asynchronous actions in Redux, and it's included by default in Redux Toolkit's configureStore.
  4. Reselect: This library helps create memoized selectors for optimizing state access, and it's often used alongside Redux Toolkit.
  5. Redux DevTools Extension: While a separate browser extension, Redux Toolkit's configureStore integrates with it by default for enhanced debugging.

In essence, when you install RTK, you are installing one package, but you are gaining access to a comprehensive set of tools and best practices, including the functionalities provided by these integrated libraries.
Although RTK is framework agnostic in this article, we will look at how to use RTK and React.
The prerequisites for this article are listed below:

Prerequisites

  1. NodeJS should be installed on your system
  2. Knowledge of React
  3. Knowledge of JavaScript
  4. Knowledge of Redux is not required, but it is an added advantage

React and Redux Toolkit

React has revolutionized the way developers build user interfaces. Its component-based architecture, virtual DOM, and declarative syntax make it a powerful library for creating dynamic web applications.
However, as applications grow, managing the state becomes challenging. Passing props through multiple components or handling complex asynchronous data can quickly lead to “prop drilling” and tangled logic. That’s where Redux Toolkit comes in — the modern, opinionated way to manage global state in React applications.

In this article, we create a simple counter application to learn how to set up Redux Toolkit and React.

Installation

We will work with Vite in this article. Vite is a super-fast build tool that replaces Create React App (CRA) for modern React development. To use it, in your terminal, run the code below:

npm create vite@latest counter-app
Enter fullscreen mode Exit fullscreen mode

You’ll be prompted with something like this:

? Select a framework: › - Use arrow-keys. Return to submit.
  Vanilla
❯ React
  Vue
  Svelte
  Others
Enter fullscreen mode Exit fullscreen mode

Choose React.
Now go into the app folder by running:

cd counter-app
Enter fullscreen mode Exit fullscreen mode

Then run the app with:

npm run dev
Enter fullscreen mode Exit fullscreen mode

After running the code above, to view the app, visit http://localhost:5173/, and you will get:

Vite and react image

Next, install Redux Toolkit and the react-redux package by running:

npm install @reduxjs/toolkit react-redux
Enter fullscreen mode Exit fullscreen mode

Now we can set up Redux Toolkit inside the app. To do this, first, we configure the Redux store by following the steps in the next section.

Configure the Store

Redux store and Redux are kind of used interchangeably; both stand for a container for JavaScript apps. And this stores the whole state of the app in an immutable object tree.

To configure the Redux store, create an app directory inside the src directory. Then create a file named store.js inside the src directory. Now add the code below to the store.js file:

// app/store.js

import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "../features/counter/counterSlice";

export const store = configureStore({
  reducer: { },
});
Enter fullscreen mode Exit fullscreen mode

After configuring the store, we need to provide the global state to our application.

Provide the store to React

To provide the store to React, replace the code in the main.jsx with the following code:

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.jsx";
import { store } from "./app/store.js";
import { Provider } from "react-redux";

createRoot(document.getElementById("root")).render(
 <StrictMode>
   <Provider store={store}>
     <App />
   </Provider>
 </StrictMode>
);
Enter fullscreen mode Exit fullscreen mode

In the code above, we used the Provider component to provide our store — our global state, to our application. Next, we create a slice.

Create a Slice

The term slice comes from splitting up a Redux state object into multiple slices of state.
A slice contains your state, reducers, and automatically generated actions for a single feature in the app. For example, a blog might have a slice for posts and another slice for comments. So in this article, our app will have a slice for counter. To create the counter slice, create a folder called features inside the src directory, and inside the features directory, create another directory called counter, then create a file named counterSlice.js in the counter directory and add the code below to the counterSlice.js:

// features/counter/counterSlice.js
import { createSlice } from "@reduxjs/toolkit";
const counterSlice = createSlice({
 name: "counter",
 initialState: { count: 0 },
 reducers: {
   increment: (state) => {
     state.count += 1;
   },
   decrement: (state) => {
     state.count -= 1;
   },
   reset: (state) => {
     state.count = 0;
   },
 },
});
export const { increment, decrement, reset } = counterSlice.actions;
export default counterSlice.reducer;
Enter fullscreen mode Exit fullscreen mode

In the code above, RTK automatically creates actions with the same name as the reducers provided, and these actions are exported.
Also, RTK uses Immer.js internally, allowing you to write “mutating” logic safely, as seen in the reducers in the code above.

Update the Store

After creating the counterSlice, we need to add the counterReducer to the store. To do this, update the code in the store.js file as seen below:

import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "../features/counter/counterSlice";
export const store = configureStore({
 reducer: {
   counter: counterReducer,
 },
});

Enter fullscreen mode Exit fullscreen mode

Now that we have added the counterReducer to the store, it is available to the entire app through the Provider.

Use the Store in Components

To do this, in the counter directory inside the features directory, create a Counter.js file and add the following code to this file:

// features/counter/Counter.js
import { useSelector, useDispatch } from "react-redux";
import { increment, decrement, reset } from "./counterSlice";

const Counter = () => {
 const count = useSelector((state) => state.counter.count);
 const dispatch = useDispatch();

 const resetAll = () => {
   dispatch(reset());
 };

 return (
   <section>
     <p>{count}</p>
     <div>
       <button onClick={() => dispatch(increment())}>+</button>
       <button onClick={() => dispatch(decrement())}>-</button>
     </div>

     <div>
       <button onClick={resetAll}>Reset</button>
     </div>
   </section>
 );
};
export default Counter;
Enter fullscreen mode Exit fullscreen mode

In the code above, the useSelector and the useDispatch hooks are imported from react-redux.
Also, the increment, decrement, and reset action creators are imported from the counterSlice.
The useSelector hook is used to get the value of count from the counterSlice, while the useDispatch hook is used to dispatch actions — created by invoking an action creator following the click of a button. So in the code above, actions created by the increment, decrement, and reset action creators are handled by the increment, decrement, and reset reducers in the counterSlice.

Now, to view the counter, we replace the codes in the App.js file with the following:

import Counter from "./features/counter/Counter";

function App() {
 return (
   <main className="App">
     <Counter />
   </main>
 );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Then replace the codes in the index.css file with the following:

* {
 margin: 0;
 padding: 0;
 box-sizing: border-box;
}

body {
 min-height: 100vh;
 font-size: 5rem;
 display: grid;
 place-content: center;
}

input,
button {
 font: inherit;
 padding: 0.5rem;
}

section {
 display: flex;
 flex-direction: column;
 justify-content: center;
 align-items: center;
}

input {
 text-align: center;
 max-width: 2.5em;
}

button {
 font-size: 2rem;
 margin: 0.5em 0 0.5em 0.5em;
 min-width: 2em;
}

button:first-child {
 margin-left: 0;
}
Enter fullscreen mode Exit fullscreen mode

Finally, when you view the app in the browser, you get:

Final counter app image

You can test the app by clicking on the increment, decrement, and reset buttons.

Conclusion

Redux Toolkit has completely transformed how developers use Redux.
What was once seen as too complicated is now simple, elegant, and enjoyable.
The above application is a simple application that shows how Redux Toolkit is set up and the overall structure of an application. However, I do hope that by following this application, you will get an understanding of Redux Toolkit and how it is used with React.
If you’re still managing state with plain Redux, now is the time to switch. You’ll write cleaner code, reduce bugs, and enjoy a better development experience.

💼 Hire Me

I'm currently available for freelance or full-time frontend or backend development work.

What I do:

  • React, Redux Toolkit, NodeJS, ExpressJS, and TailwindCSS
  • Building scalable web applications
  • Creating responsive, user-friendly UIs

📧 Email: Leave a messsage

🌐 Portfolio: My portfolio

If you like my work, let’s collaborate!

Top comments (0)