Skip to main content

`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:

  1. createSlice: We create a slice with the name todos, an initial state of an empty array, and a reducers object.
  2. addTodo: We've used the prepare callback to customize the payload of our addTodo action.
  3. toggleTodo: This reducer finds the corresponding to-do and toggles its completed property.

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:

  • createSlice is 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.

Further Reading