What is React?
React is a javaScript
library that use to build our user interface for applications.
What is useReducer
useReducer
is a react hook that is used to implement our complex state of applications.
In this simple todo app I have used react with typescript template
Step 1:
First of all, create a project called todo using
create-react-app
npx create-react-app todo --template typescript
After creating the projectcd
to todo folder then run
npm start
oryarn start
Step 2:
- Create two folder called containers , components
- Create a file called Todos.tsx in containers
- Import Todos.tsx file in App.tsx and use it
import * as React from "react"; import Todos from "./container/Todos"; const App: React.FC = () => { return <Todos />; }; export default App;
- Create an interface that will represent the blueprint of a todo item in Todos.tsx file
export interface TodosProps { id: string; todoName: string; isComplete: boolean; }
- Create interfaces for various activities of the app like add todo item, remove todo item and toggle the todo to check that todo item is completed or not
interface AddTodoAction { type: "ADD_TODO"; payload: { name: string }; } interface ModifyTodoAction { type: "TOGGLE_TODO" | "DELETE_TODO"; payload: { id: string }; }
- action type
export type TodoAction = AddTodoAction | ModifyTodoAction
- Create a reducer function called todoReducer that is used with useReducer to control the state with action.
const todoReducer = (todos: Array<TodosProps>, action: TodoAction) => { switch (action.type) { case "ADD_TODO": return [...todos, newTodo(action.payload.name)]; case "TOGGLE_TODO": return todos.map((todo) => { if (todo.id === action.payload.id) { return { ...todo, isComplete: !todo.isComplete }; } return todo; }); case "DELETE_TODO": return todos.filter((todo) => todo.id !== action.payload.id); default: return todos; } };
- Create a new todo item structure with this function
const newTodo = (todoName: string): TodosProps => { return { id: uuidv4(), todoName: todoName, isComplete: false }; };
- Todos.tsx
import * as React from "react"; import { useReducer } from "react"; import { v4 as uuidv4 } from "uuid"; import Todo from "../components/Todo"; import TodoInput from "../components/TodoInput"; export interface TodosProps { id: string; todoName: string; isComplete: boolean; } interface AddTodoAction { type: "ADD_TODO"; payload: { name: string }; } interface ModifyTodoAction { type: "TOGGLE_TODO" | "DELETE_TODO"; payload: { id: string }; } export type TodoAction = AddTodoAction | ModifyTodoAction; const todoReducer = (todos: Array<TodosProps>, action: TodoAction) => { switch (action.type) { case "ADD_TODO": return [...todos, newTodo(action.payload.name)]; case "TOGGLE_TODO": return todos.map((todo) => { if (todo.id === action.payload.id) { return { ...todo, isComplete: !todo.isComplete }; } return todo; }); case "DELETE_TODO": return todos.filter((todo) => todo.id !== action.payload.id); default: return todos; } }; const newTodo = (todoName: string): TodosProps => { return { id: uuidv4(), todoName: todoName, isComplete: false }; }; const Todos: React.FC = () => { const [todos, dispatch] = useReducer(todoReducer, []); const renderTodos = todos.map((todo) => ( <Todo key={todo.id} id={todo.id} todoName={todo.todoName} isComplete={todo.isComplete} dispatch={dispatch} /> )); console.log(todos); return ( <div> <TodoInput dispatch={dispatch} /> {renderTodos} </div> ); }; export default Todos;
- Create a file called TodoInput.tsx in components folder
TodoInput.tsx
This component is responsible for rendering a form with an input field and a submit button
import * as React from "react"; import { useState } from "react"; import { TodoAction } from "../container/Todos"; interface TodoInputProps { dispatch: React.Dispatch<TodoAction>; } const TodoInput: React.FC<TodoInputProps> = ({ dispatch }) => { const [todoName, setTodoName] = useState(""); const handleChange = (evt: React.FormEvent<HTMLInputElement>) => { setTodoName(evt.currentTarget.value); }; const handleSubmit = (evt: React.FormEvent) => { evt.preventDefault(); dispatch({ type: "ADD_TODO", payload: { name: todoName } }); setTodoName(""); }; return ( <form onSubmit={handleSubmit}> <input type="text" placeholder="Type your todo...." value={todoName} onChange={handleChange} /> <button type="submit">Add Todo</button> </form> ); }; export default TodoInput;
- Display all todo item in Todo.tsx file in components folder
import * as React from "react"; import { TodosProps, TodoAction } from "../container/Todos"; export interface Props extends TodosProps { dispatch: React.Dispatch<TodoAction>; } const Todo: React.FC<Props> = ({ dispatch, id, isComplete, todoName }) => { const handleDelete = (id: string) => { dispatch({ type: "DELETE_TODO", payload: { id: id }, }); }; const handleToggle = (id: string) => { dispatch({ type: "TOGGLE_TODO", payload: { id: id }, }); }; return ( <div> <div> <p style={{ textDecoration: `${isComplete ? "line-through" : ""}` }}> {todoName} </p> </div> <div> <button onClick={() => handleToggle(id)}>Toggle</button> <button onClick={() => handleDelete(id)}>Delete</button> </div> </div> ); }; export default Todo;
Top comments (0)