DEV Community

Harsh Mishra
Harsh Mishra

Posted on

Redux Simple Guide

A Comprehensive Guide to Redux Toolkit: Managing Global State Efficiently in React

Introduction

In React, managing state is a critical part of building interactive applications. While useState and useReducer work well for managing local component state, when you need to manage global state shared across multiple components, things get more complicated. This is where Redux shines—especially with the modern Redux Toolkit.

Redux has evolved over time, and the Redux Toolkit provides a set of utilities that make it easier to write Redux logic without the boilerplate code of the past. In this guide, we will walk you through the core concepts of Redux Toolkit, its key features, and how to use it effectively in modern React applications. By the end of this article, you will be able to build a scalable global state management system in your React application using Redux Toolkit.

We’ll also build a To-Do List project to showcase how Redux Toolkit simplifies state management with slices, actions, reducers, and the Redux store.


Table of Contents

  1. Understanding Redux Toolkit
  2. Core Concepts of Redux Toolkit
    • Slices
    • Actions and Reducers
    • createSlice API
    • The Redux Store
  3. Setting Up Redux Toolkit in a React App
  4. Building a Mini Project: Global To-Do List with Redux Toolkit
  5. Conclusion

Understanding Redux Toolkit

Redux Toolkit is the modern way to write Redux logic. It is a set of tools that helps you avoid the traditional boilerplate of Redux, making it easier to set up and maintain your store, actions, reducers, and state logic.

In traditional Redux, managing state required creating action types, action creators, and reducers separately. Redux Toolkit consolidates and simplifies this process with a few functions:

  • createSlice: Defines a slice of the Redux state and auto-generates actions and reducers.
  • configureStore: Configures the Redux store, including middleware like Redux DevTools.

Core Concepts of Redux Toolkit

Before we dive into the project, let’s cover some of the core concepts and APIs provided by Redux Toolkit.


1. Slices

A slice in Redux Toolkit represents a part of the Redux state and the associated reducer logic. With createSlice, Redux Toolkit combines actions and reducers, automatically generating action creators based on the reducer methods you define.

Here’s an example of creating a slice for managing a to-do list:

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

const todoSlice = createSlice({
  name: 'todos',
  initialState: [],
  reducers: {
    addTodo: (state, action) => {
      state.push({ id: Date.now(), text: action.payload, completed: false });
    },
    toggleTodo: (state, action) => {
      const todo = state.find(todo => todo.id === action.payload);
      if (todo) {
        todo.completed = !todo.completed;
      }
    },
    removeTodo: (state, action) => {
      return state.filter(todo => todo.id !== action.payload);
    }
  }
});

export const { addTodo, toggleTodo, removeTodo } = todoSlice.actions;
export default todoSlice.reducer;
Enter fullscreen mode Exit fullscreen mode
  • Reducers: Functions that specify how the state changes in response to actions.
  • Actions: Generated by createSlice, based on the reducer names. For example, addTodo, toggleTodo, and removeTodo are actions that are automatically dispatched.

2. Actions and Reducers

In Redux Toolkit, actions and reducers are combined within a slice. Redux Toolkit automatically generates action creators and action types, so you don't have to manually write them as you would in the traditional Redux setup.

Here’s a typical Redux Toolkit action and reducer:

addTodo: (state, action) => {
  state.push({ id: Date.now(), text: action.payload, completed: false });
}
Enter fullscreen mode Exit fullscreen mode
  • Action: addTodo is an action that gets triggered with dispatch(addTodo('Task Text')).
  • Reducer: The function inside the createSlice handles the state update.

3. createSlice API

The createSlice function allows you to define a slice of state, the reducers that handle updates, and the automatically generated action creators.

const slice = createSlice({
  name: 'todos',
  initialState: [],
  reducers: {
    // Reducer functions here
  }
});
Enter fullscreen mode Exit fullscreen mode
  • name: A string representing the name of the slice, used in the action types.
  • initialState: The initial value for the state.
  • reducers: A set of functions that define how the state should be updated in response to actions.

4. The Redux Store

Once your slices are defined, you need to configure your store to combine them and apply middleware.

import { configureStore } from '@reduxjs/toolkit';
import todoReducer from './todoSlice';

const store = configureStore({
  reducer: {
    todos: todoReducer
  }
});

export default store;
Enter fullscreen mode Exit fullscreen mode
  • configureStore: Automatically adds useful middleware, such as Redux DevTools.

Setting Up Redux Toolkit in a React App

  1. Install Redux Toolkit and React-Redux

First, make sure to install Redux Toolkit and React-Redux in your React project:

npm install @reduxjs/toolkit react-redux
Enter fullscreen mode Exit fullscreen mode
  1. Create Redux Slices and Store

Create the slices and the store, as we showed earlier.

  1. Set Up the Provider

Next, wrap your app with the Redux Provider to allow access to the Redux store in any component.

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import { store } from './store';

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
Enter fullscreen mode Exit fullscreen mode

Building a Mini Project: Global To-Do List with Redux Toolkit

Let’s create a global To-Do List app using Redux Toolkit, with 3 slices: todos, auth, and theme.


Step 1: Create the Redux Slices

todosSlice.js: Manages to-do list state.

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

const todoSlice = createSlice({
  name: 'todos',
  initialState: [],
  reducers: {
    addTodo: (state, action) => {
      state.push({ id: Date.now(), text: action.payload, completed: false });
    },
    toggleTodo: (state, action) => {
      const todo = state.find(todo => todo.id === action.payload);
      if (todo) todo.completed = !todo.completed;
    },
    removeTodo: (state, action) => {
      return state.filter(todo => todo.id !== action.payload);
    }
  }
});

export const { addTodo, toggleTodo, removeTodo } = todoSlice.actions;
export default todoSlice.reducer;
Enter fullscreen mode Exit fullscreen mode

authSlice.js: Manages authentication state.

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

const authSlice = createSlice({
  name: 'auth',
  initialState: { user: null },
  reducers: {
    login: (state, action) => {
      state.user = action.payload;
    },
    logout: (state) => {
      state.user = null;
    }
  }
});

export const { login, logout } = authSlice.actions;
export default authSlice.reducer;
Enter fullscreen mode Exit fullscreen mode

themeSlice.js: Manages theme state (dark or light mode).

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

const themeSlice = createSlice({
  name: 'theme',
  initialState: { isDarkMode: false },
  reducers: {
    toggleTheme: (state) => {
      state.isDarkMode = !state.isDarkMode;
    }
  }
});

export const { toggleTheme } = themeSlice.actions;
export default themeSlice.reducer;
Enter fullscreen mode Exit fullscreen mode

Step 2: Set Up the Redux Store

store.js: Combine the slices into a Redux store.

import { configureStore } from '@reduxjs/toolkit';
import todoReducer from './todosSlice';
import authReducer from './authSlice';
import themeReducer from './themeSlice';

const store = configureStore({
  reducer: {
    todos: todoReducer,
    auth: authReducer,
    theme: themeReducer
  }
});

export default store;
Enter fullscreen mode Exit fullscreen mode

Step 3: Create the Components

TodoList.js: Displays the to-do list and allows interaction.

import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { addTodo, toggleTodo, removeTodo } from './todosSlice';

const TodoList = () => {
  const [task, setTask] = useState('');
  const todos = useSelector(state => state.todos);
  const dispatch = useDispatch();

  const handleAdd = () => {
    if (task.trim()) {
      dispatch(addTodo(task));
      setTask('');
    }
  };

  return (
    <div>
      <h2>To-Do List</h2>
      <input
        value={task}
        onChange={(e) => setTask(e.target.value)}
        placeholder="Enter a new task"
      />
      <button onClick={handleAdd}>Add Task</button>

      <ul>
        {todos.map(todo => (


          <li key={todo.id}>
            {todo.text} - {todo.completed ? 'Completed' : 'Pending'}
            <button onClick={() => dispatch(toggleTodo(todo.id))}>Toggle</button>
            <button onClick={() => dispatch(removeTodo(todo.id))}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoList;
Enter fullscreen mode Exit fullscreen mode

App.js: Main app component that toggles theme and shows the To-Do List.

import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { toggleTheme } from './themeSlice';
import TodoList from './TodoList';

function App() {
  const dispatch = useDispatch();
  const isDarkMode = useSelector(state => state.theme.isDarkMode);

  return (
    <div style={{ backgroundColor: isDarkMode ? 'black' : 'white', color: isDarkMode ? 'white' : 'black' }}>
      <button onClick={() => dispatch(toggleTheme())}>Toggle Theme</button>
      <TodoList />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this guide, we covered how to manage global state in a React application using Redux Toolkit. We demonstrated the core concepts of slices, actions, reducers, and how to set up the Redux store. We also built a mini project—a to-do list app—using Redux Toolkit with three slices: todos, auth, and theme.

Redux Toolkit simplifies Redux usage by reducing boilerplate code and improving the development experience. It helps you manage state efficiently in large-scale React applications, offering an easy-to-use solution for complex state logic.

Happy coding! 🚀

Top comments (0)