Building a Todo App with Redux and React

Munideepa Vallambai
4 min readMar 25, 2024

In today’s world of web development, managing state effectively is crucial for creating dynamic and interactive user interfaces. Redux, a predictable state container for JavaScript apps, provides a robust solution for managing application state in complex React applications. In this tutorial, we’ll walk through the process of building a simple Todo application using Redux and React, demonstrating how Redux can streamline state management and enhance application scalability.

Prerequisites:

Before diving into the tutorial, make sure you have a basic understanding of React and Redux concepts. Additionally, ensure you have Node.js and npm (Node Package Manager) installed on your system.

Setting Up the Project:

To begin, let’s set up our project structure and install the necessary dependencies. We’ll use Create React App to bootstrap our React application and then integrate Redux for state management.

First, create a new React application by running the following command in your terminal:

npx create-react-app redux-todo-app

Once the project is created, navigate into the project directory:

cd redux-todo-app

Now, let’s install Redux and React Redux, which provides React bindings for Redux:

npm install redux react-redux @reduxjs/toolkit

Creating Redux Actions, Reducers, and Store:

In Redux, actions are payloads of information that send data from your application to the Redux store. Reducers specify how the application’s state changes in response to actions. Let’s create actions and reducers for adding and removing Todos.

Inside the src directory, create an actions folder with an actions.js file containing the following code:

// actions.js

export const addTodo = (todo) => ({
type: 'ADD_TODO',
payload: todo
});

export const removeTodo = (todoId) => ({
type: 'REMOVE_TODO',
payload: todoId
});

Next, create a reducers folder with a reducer.js file:

// reducer.js

const initialState = {
todos: []
};

const todoReducer = (state = initialState, action) => {
switch (action.type) {
case 'ADD_TODO':
return {
...state,
todos: [...state.todos, action.payload]
};
case 'REMOVE_TODO':
return {
...state,
todos: state.todos.filter(todo => todo.id !== action.payload)
};
default:
return state;
}
};

export default todoReducer;

Now, let’s configure the Redux store. Create a Store folder with a Store.js file:

// Store.js

import { configureStore } from '@reduxjs/toolkit';
import rootReducer from '../reducers/reducer';

const store = configureStore({
reducer: rootReducer
});

export default store;

Building Components:

Our Todo application will consist of two main components: AddTodoForm for adding new Todos and TodoList for displaying and managing existing Todos. Let’s create these components.

Create a Components folder inside the src directory. Inside it, create two files: AddTodoForm.js and TodoList.js.

AddTodoForm Component:

// AddTodoForm.js

import React, { useState } from 'react';
import { useDispatch } from 'react-redux';
import { addTodo } from '../actions/actions';
import '../styles/AddTodoForm.css';

const AddTodoForm = () => {
const [text, setText] = useState('');
const dispatch = useDispatch();

const handleSubmit = (e) => {
e.preventDefault();
if (text.trim()) {
dispatch(addTodo({
id: Math.random(),
text
}));
}
setText('');
};

return (
<form onSubmit={handleSubmit} className='add-todo-form'>
<input type='text' value={text} onChange={(e) => setText(e.target.value)} className='todo-input' />
<button type='submit' className='add-button'>Add Todo</button>
</form>
);
};

export default AddTodoForm;

TodoList Component:

// TodoList.js

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { removeTodo } from '../actions/actions';
import '../styles/TodoList.css';

const TodoList = () => {
const todos = useSelector(state => state.todos);
const dispatch = useDispatch();

const handleRemoveTodo = (id) => {
dispatch(removeTodo(id));
};

return (
<ul className='todo-list'>
{todos.map(todo => (
<li key={todo.id} className='todo-item'>
{todo.text}
<button className='delete-button' onClick={() => handleRemoveTodo(todo.id)}>Delete</button>
</li>
))}
</ul>
);
};

export default TodoList;

Styling Components:

Let’s add some basic styling to our components for better visual presentation. Create a styles folder inside the src directory and add the following CSS files:

AddTodoForm.css:

/* AddTodoForm.css */
.add-todo-form {
margin-bottom: 20px;
}

.todo-input {
padding: 8px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 5px;
}

.add-button {
padding: 8px 20px;
font-size: 16px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}

TodoList.css:

/* TodoList.css */
.todo-list {
list-style-type: none;
padding: 0;
}

.todo-item {
margin-bottom: 10px;
}

.delete-button {
margin-left: 10px;
padding: 5px 10px;
background-color: #ff5733;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}

Integrating Components into App:

Now, let’s integrate our components into the main App component.

// App.js

import React from 'react';
import { Provider } from 'react-redux';
import store from './Store/Store';
import TodoList from './Components/TodoList';
import AddTodoForm from './Components/AddTodoForm';
import './App.css';

const App = () => {
return (
<Provider store={store}>
<div className="app-container">
<h1 className="app-title">Todo App</h1>
<AddTodoForm />
<TodoList />
</div>
</Provider>
);
};

export default App;

App.css:

/* App.css */
.app-container {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
max-width: 500px;
padding: 20px;
background-color: #f9f9f9;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.app-title {
text-align: center;
margin-bottom: 20px;
}

With this App.css file, we're defining styles for the main application container, positioning it in the center of the screen with some padding and styling. The .app-title class is used to style the title of the Todo application.

Conclusion:

In this tutorial, we’ve learned how to build a simple Todo application using Redux and React. We’ve covered the basics of Redux actions, reducers, and store configuration, as well as creating functional components and integrating them into a React application. By leveraging Redux for state management, we’ve ensured a predictable and scalable approach to managing application state, making it easier to maintain and extend our Todo application. Feel free to customize and expand upon this project

--

--