Combining the Puzzle Pieces
Let's now look at a working to-do list application that uses the concepts learned in the previous lessons.
We'll cover the following...
To-do list app example
We now know how to use the connect()
method and why we need a Provider
. Let’s look at a more detailed and complete example that outlines a totally functional to-do list app. It allows us to add new to-do items, mark them as complete or not, and allows us to remove them if we want:
import React, { useState } from 'react'; import { connect } from 'react-redux'; import { addTodo, removeTodo, changeStatus } from './store/todos/actions'; const TodoList = (props) => { const [todoText, setTodoText] = useState(''); return ( <div> <p>{props.todos.length} Todos.</p> <ul> {props.todos.map((todo) => ( <li key={todo.id}> <button type="button" onClick={() => { props.removeTodo(todo.id); }} > remove </button> <label style={{ textDecoration: todo.done ? 'line-through' : 'none' }} > <input type="checkbox" name={todo.id} checked={Boolean(todo.done)} onChange={(e) => { const { name, checked } = e.target; props.changeStatus(name, checked); }} /> {todo.text} </label> </li> ))} </ul> <input onChange={(e) => setTodoText(e.target.value)} value={todoText} /> <button type="button" onClick={() => { props.addTodo(todoText); setTodoText(''); }} > add </button> </div> ); }; const mapStateToProps = (state) => ({ todos: state.todos, }); const mapDispatchToProps = { addTodo, removeTodo, changeStatus, }; export default connect( mapStateToProps, mapDispatchToProps )(TodoList);
We’ve defined the todosReducer
as well as addTodo
, removeTodo
, and changeStatus
actions. To aid readability, both reducers and actions have been extracted into their own files within the ./store/todos directory.
Note: There’s always heated debate about how folders and files should be structured within an application. Some find a separation by the domain (for ...