Effortless State Management: Integrating Redux Toolkit with React and Next.js

As web applications become more complex, managing state becomes a key challenge for developers. That's where Redux comes in, providing a predictable and centralized way to manage application state. However, setting up and configuring Redux can be a hassle, which is where Redux Toolkit comes in. In this article, we'll explore how to use Redux Toolkit with React and Next.js to make state management a breeze.

Setting up Redux Toolkit

The first step to using Redux Toolkit is installing it. We can do that easily with npm or yarn:

npm install @reduxjs/toolkit

Once installed, we can create our Redux store with a single line of code:

import { configureStore } from "@reduxjs/toolkit";

const store = configureStore();

This gives us a fully functional Redux store with default middleware, dev tools, and a default root reducer. We can start using this store right away, but to make it more useful, we need to create slices.

Creating Slices

Slices are pieces of our global application state that we can manage with Redux Toolkit. They're called slices because they represent a slice of our overall state. We can create slices easily with the createSlice function:

import { createSlice } from "@reduxjs/toolkit";

const counterSlice = createSlice({
  name: "counter",
  initialState: 0,
  reducers: {
    increment(state) {
      return state + 1;
    decrement(state) {
      return state - 1;

This creates a slice called "counter" that manages a single integer value and has two reducers for incrementing and decrementing that value. We can add as many slices as we want to manage different parts of our state.

Connecting Components to the Store

Now that we have our store and slices, we're ready to start using Redux Toolkit in our React components. To do that, we first need to connect our component to the store. We can do that easily with the connect function:

import { connect } from "react-redux";

const mapStateToProps = (state) => ({
  counter: state.counter,

export default connect(
  { increment: counterSlice.actions.increment, decrement: counterSlice.actions.decrement }

This creates a new component called Counter that is connected to the Redux store. We're using mapStateToProps to map the counter value from our state to a prop called counter, and we're using mapDispatchToProps to map our increment and decrement actions to prop functions.

Updating the Store with Actions

Now that our component is connected to the store, we can update our state with the actions we defined in our slices. We can do that by calling the actions directly:

import { useDispatch } from "react-redux";

function Counter() {
  const dispatch = useDispatch();

  return (
      <button onClick={() => dispatch(counterSlice.actions.increment())}>+

We're using the useDispatch hook to get access to the dispatch function, and then calling our increment and decrement actions when the buttons are clicked. This will update our state, which will then trigger a re-render of our connected components that use that state.

Optimizing Performance with createSelector

One issue with Redux is that it can be slow to re-render components when the state changes. To improve performance, we can use the createSelector function from Redux Toolkit. This function creates a memoized selector that only re-runs when its inputs change:

import { createSelector } from "@reduxjs/toolkit";

const selectCounter = (state) => state.counter;

export const selectCounterValue = createSelector(
  (counter) => counter

We're using selectCounter to select the counter value from our state, and then passing that value to our selectCounterValue selector. This selector will only re-run when the counter value changes, which can significantly improve performance for large applications.


Redux Toolkit is a powerful tool for managing application state in React and Next.js applications. With Redux Toolkit, we can effortlessly create a Redux store and slices, connect our components to the store, update the store with actions, and optimize performance with memoized selectors. Give it a try and see how much easier it makes managing your application state!