React Removing Todos

Removing ToDo Items

In this post I'm commenting on the code required to remove an individual to-do to remove it from the application, including from the user interface.

TodoList.js:
· When a user clicks the trash (delete) icon an onClick event dispatches an action of type "REMOVE_TODO" which gets picked up in reducer.js (reducer.js line 57). The array.filter method is used to loop over and parse out the selected todo's id, hence rebuilding the entire todo list without the deleted todo item.

TodoList.js

import React, { useContext } from "react"; //in order to consume context need to import useContext from React, don't forget!
import TodosContext from "../context"; //the actual data that will be consumed

export default function TodoList() {
  const { state, dispatch } = useContext(TodosContext); //destructure from the context
  const title =
    state.todos.length > 0 ? `${state.todos.length} Todos` : "Nothing to do!";

  return (
    <div className="container mx-auto max-w-md text-center font-mono">
      <h1 className="text-bold">{title}</h1>
      <ul className="list-reset text-white p-0">
        {state.todos.map(todo => (
          <li
            key={todo.id}
            className="flex items-center bg-orange-dark border-black border-dashed border-2 my-2 py-4"
            style={{ backgroundColor: "orange" }}
          >
            <span
              className={`flex-1 ml-12 text-black cursor-pointer ${todo.complete &&
                "line-through text-gray-darkest"}`}
              onDoubleClick={() =>
                dispatch({ type: "TOGGLE_TODO", payload: todo })
              }
            >
              {todo.text}
            </span>
            <button
              onClick={() =>
                dispatch({ type: "SET_CURRENT_TODO", payload: todo })
              }
            >
              {" "}
              <img
                src="https://icon.now.sh/edit/0050c5"
                alt="edit icon"
                className="h-6"
              />
            </button>
            <button>
              {" "}
              <img
                src="https://icon.now.sh/delete/8b0000"
                alt="delete icon"
                className="h-6"
                onClick={() => dispatch({ type: "REMOVE_TODO", payload: todo })}
              />
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
}


reducer.js

import uuidv4 from 'uuid/v4'

export default function reducer(state, action){
    switch(action.type){
        case "ADD_TODO" :
            if(!action.payload){
                return state;
            } 
            if(state.todos.findIndex(t => t.text === action.payload) > -1) {
                return state;
            }
            const newTodo = {
                id: uuidv4(),
                text: action.payload,
                completed: false
            }
            const addedTodos = [...state.todos, newTodo]
            return {
                ...state,
                todos: addedTodos
            }

        case "SET_CURRENT_TODO" : 
            return {
                ...state,
                currentTodo: action.payload
            }    

        case "TOGGLE_TODO" : 
            const toggledTodos = state.todos.map(t => 
                t.id === action.payload.id ? {...action.payload, complete: !action.payload.complete} : t)
                return {
                    ...state, 
                    todos: toggledTodos
                }
        case "UPDATE_TODO": 
            if(!action.payload){
                return state;
            } 
            if(state.todos.findIndex(t => t.text === action.payload) > -1) {
                return state;
            }
            const updatedTodo = { ...state.currentTodo, text: action.payload }
            const updatedTodoIndex = state.todos.findIndex(
                t => t.id === state.currentTodo.id
            )
            const updatedTodos = [
                ...state.todos.slice(0, updatedTodoIndex),
                updatedTodo,
                ...state.todos.slice(updatedTodoIndex + 1)
            ]
            return {
                ...state,
                currentTodo: {},
                todos: updatedTodos
            }        
        case "REMOVE_TODO" : 
            const filteredTodos = state.todos.filter(t => t.id !== action.payload.id);
            const isRemovedTodo = state.currentTodo.id === action.payload.id ? {} : state.currentTodo;
            return {
                ...state,
                currentTodo: isRemovedTodo,
                todos: filteredTodos
            }       
        default: 
            return state;
    }
}


Link your website to this page! Copy and paste the URL below:
http://www.cfsnap.com/react/react-removing-todos/