`configureStore` and `createSlice` (Part 2): A Practical Example of Creating a Slice #115
📖 Introduction
Following our introduction to configureStore and createSlice, this article provides a practical, hands-on example of how to use these functions in a React application. We will build a simple to-do list application to demonstrate how to create a slice and use it to manage the state of our application.
📚 Prerequisites
Before we begin, please ensure you have a solid grasp of the following concepts:
- All concepts from Part 1 of this series.
- How to set up a Redux store and connect it to a React application.
🎯 Article Outline: What You'll Master
In this article, you will learn:
- ✅ Creating a Slice: How to create a slice for a to-do list application.
- ✅ Using the Slice in a Component: How to use the generated actions and reducer in a React component.
- ✅ Practical Application: Building a simple to-do list application that uses Redux Toolkit to manage its state.
🧠 Section 1: The Core Concepts of a To-Do List Slice
For our to-do list application, we will create a single slice to manage the state of our to-dos. This slice will include:
- An initial state with an empty array of to-dos.
- Reducers for adding, toggling, and removing to-dos.
The createSlice function will automatically generate the corresponding action creators and action types for us.
💻 Section 2: Deep Dive - Implementation and Walkthrough
Let's build our to-do list application.
2.1 - The todosSlice.js File
First, let's create a todosSlice.js file in our features/todos directory.
// features/todos/todosSlice.js
import { createSlice } from '@reduxjs/toolkit';
let nextTodoId = 0;
export const todosSlice = createSlice({
name: 'todos',
initialState: [],
reducers: {
addTodo: {
reducer(state, action) {
const { id, text } = action.payload;
state.push({ id, text, completed: false });
},
prepare(text) {
return { payload: { text, id: nextTodoId++ } };
}
},
toggleTodo(state, action) {
const todo = state.find(todo => todo.id === action.payload);
if (todo) {
todo.completed = !todo.completed;
}
},
},
});
export const { addTodo, toggleTodo } = todosSlice.actions;
export default todosSlice.reducer;
Step-by-Step Code Breakdown:
createSlice: We create a slice with the nametodos, an initial state of an empty array, and areducersobject.addTodo: We've used thepreparecallback to customize the payload of ouraddTodoaction.toggleTodo: This reducer finds the corresponding to-do and toggles itscompletedproperty.
2.2 - The store.js File
Now, let's add our todosReducer to our store.
// app/store.js
import { configureStore } from '@reduxjs/toolkit';
import todosReducer from '../features/todos/todosSlice';
export default configureStore({
reducer: {
todos: todosReducer,
},
});
2.3 - The TodoList and AddTodo Components
Now, let's create the components to display and interact with our to-do list.
// components/TodoList.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { toggleTodo } from '../features/todos/todosSlice';
function TodoList() {
const todos = useSelector(state => state.todos);
const dispatch = useDispatch();
return (
<ul>
{todos.map(todo => (
<li
key={todo.id}
onClick={() => dispatch(toggleTodo(todo.id))}
style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
>
{todo.text}
</li>
))}
</ul>
);
}
export default TodoList;
// components/AddTodo.js
import React, { useState } from 'react';
import { useDispatch } from 'react-redux';
import { addTodo } from '../features/todos/todosSlice';
function AddTodo() {
const [text, setText] = useState('');
const dispatch = useDispatch();
const handleSubmit = e => {
e.preventDefault();
if (text.trim()) {
dispatch(addTodo(text));
setText('');
}
};
return (
<form onSubmit={handleSubmit}>
<input value={text} onChange={e => setText(e.target.value)} />
<button type="submit">Add Todo</button>
</form>
);
}
export default AddTodo;
💡 Conclusion & Key Takeaways
In this article, we've built a practical example of how to use createSlice to create a slice for a to-do list application. We've seen how to define reducers, generate actions, and use them in our React components.
Let's summarize the key takeaways:
createSliceis a powerful function that simplifies the creation of Redux logic.- It automatically generates action creators and action types.
- It uses Immer under the hood to allow for "mutating" logic in reducers.
Challenge Yourself:
To solidify your understanding, try to add a removeTodo action to the todosSlice that removes a to-do item from the list.
➡️ Next Steps
You now have a solid understanding of how to use createSlice to create a slice. In the next article, "Async Logic with createAsyncThunk (Part 1)", we will learn how to handle asynchronous logic in Redux Toolkit.
Thank you for your dedication. Stay curious, and happy coding!
glossary
- Prepare Callback: A function that can be used to customize the payload of an action.