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
- Understanding Redux Toolkit
-
Core Concepts of Redux Toolkit
- Slices
- Actions and Reducers
-
createSlice
API - The Redux Store
- Setting Up Redux Toolkit in a React App
- Building a Mini Project: Global To-Do List with Redux Toolkit
- 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;
- 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
, andremoveTodo
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 });
}
-
Action:
addTodo
is an action that gets triggered withdispatch(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
}
});
-
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;
-
configureStore
: Automatically adds useful middleware, such as Redux DevTools.
Setting Up Redux Toolkit in a React App
- 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
- Create Redux Slices and Store
Create the slices and the store, as we showed earlier.
- 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')
);
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;
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;
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;
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;
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;
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;
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)