React on Firebase!๐Ÿ”ฅ: Part 4

Subrata ChSubrata Ch
4 min read

In this part of the series (Part 4), we will add a delete function so users can remove tasks. Next to each task, we will add a delete button that can be used to delete a specific task. We will also add a pre-delete confirmation to prevent accidental deletions. For this update, we will only modify our App.jsx file; the rest of the app's code will remain the same. As before, the comments will help you understand the purpose of each code snippet.

App.jsx :

import React, { useState } from "react"; // Importing React and useState hook
import "./App.css"; // Importing custom CSS styles

const App = () => {
  // Main App component

  const [tasks, setTasks] = useState([]); // State to store the list of tasks
  const [taskInput, setTaskInput] = useState(""); // State to store the current input value
  const [error, setError] = useState(""); // State to store any validation error messages

  const addTask = (task) => {
    // Function to add a new task to the list
    setTasks([...tasks, task]); // Update tasks state by adding the new task
  };

  const deleteTask = (id) => {
    // Function to delete a task by its id
    setTasks(tasks.filter((task) => task.id !== id)); // Filter out the task with the matching id
  };

  const toggleTaskDone = (id) => {
    // Function to toggle the 'done' status of a task
    setTasks(
      tasks.map((task) =>
        task.id === id ? { ...task, done: !task.done } : task // Toggle 'done' if id matches, otherwise return task as is
      )
    );
  };

  const handleSubmit = (e) => {
    // Function to handle form submission
    e.preventDefault(); // Prevent default form submission behavior

    if (taskInput.trim() === "") {
      // Check if the input is empty or only whitespace
      setError("Task cannot be empty"); // Set error message
    } else {
      addTask({ id: Date.now(), text: taskInput, done: false }); // Add the new task with a unique id and 'done' set to false
      setTaskInput(""); // Clear the input field
      setError(""); // Clear any existing error message
    }
  };

  const confirmDelete = (id) => {
    // Function to confirm deletion of a task
    const isConfirmed = window.confirm(
      "Are you sure you want to delete this task?"
    ); // Display a confirmation dialog
    if (isConfirmed) {
      // If the user confirms deletion
      deleteTask(id); // Delete the task
    }
  };

  const sortedTasks = [...tasks].sort((a, b) => a.done - b.done); // Sort tasks so that completed tasks are at the bottom

  return (
    <div className="App container mt-4">
      {/* Main container with some Bootstrap spacing */}
      <h1 className="text-center mb-4">To-Do List v3 - DELETE Task</h1>
      {/* Header for the app */}

      <form onSubmit={handleSubmit} className="mb-4">
        {/* Form for adding a new task */}
        <div className="input-group">
          {/* Bootstrap input group for better styling */}
          <input
            type="text"
            className={`form-control ${error ? "is-invalid" : ""}`}
            value={taskInput}
            onChange={(e) => setTaskInput(e.target.value)}
            placeholder="Add a new task"
          />
          {/* Text input field with dynamic class based on error state */}
          <button type="submit" className="btn btn-primary">
            Add Task
          </button>
          {/* Submit button to add the task */}
        </div>
        {error && <div className="invalid-feedback d-block alert alert-danger">{error}</div>}
        {/* Display validation error message if it exists */}
      </form>

      <ul className="list-group">
        {/* Unordered list to display tasks */}
        {sortedTasks.map((task, index) => (
          <li
            key={task.id}
            className={`list-group-item d-flex justify-content-between align-items-center ${
              task.done ? "list-group-item-secondary" : ""
            }`}
          >
            {/* List item with dynamic class based on task completion */}
            <span
              className={
                task.done ? "text-decoration-line-through text-danger" : ""
              }
              onClick={() => toggleTaskDone(task.id)}
            >
              {index + 1}: {task.text}
            </span>
            {/* Task text with a strike-through and red text if completed; click toggles completion */}
            <button
              onClick={() => confirmDelete(task.id)}
              className="btn btn-danger btn-sm text-decoration-none"
            >
              Delete
            </button>
            {/* Delete button with confirmation dialog */}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default App; // Export the App component as the default export

I also have added a pre-delete confirmation, before deleting. together, they look like as below ๐ŸŒฌ:

๐Ÿ— Key things to watch out for: ๐Ÿ‘€

โžก New deleteTask() function: ๐Ÿ—‘

  const deleteTask = (id) => {
    // Function to delete a task by its id
    setTasks(tasks.filter((task) => task.id !== id)); 
    // Filter out the task with the matching id
  };

โžก Use of confirmDelete(): ๐Ÿšฎ

  const confirmDelete = (id) => {
    // Function to confirm deletion of a task
    const isConfirmed = window.confirm(
      "Are you sure you want to delete this task?"
    ); // Display a confirmation dialog
    if (isConfirmed) {
      // If the user confirms deletion
      deleteTask(id); // Delete the task
    }
  };

โžก Binding confirmDelete(task.id) function with the submit button's onClick event: ๐Ÿ“ฃ

<button
  onClick={() => confirmDelete(task.id)}
  className="btn btn-danger btn-sm text-decoration-none" >
  Delete
</button>

This wraps up the addition of our planned key features to the app. However, we have not connected our app to the Google Firebase ๐Ÿ”ฅ Realtime Database yet, but we will include it in the final part (Part 5). This way, anyone can use the application without the database if they prefer. In our next part, we will add and configure the Firebase database and push this data to the real-time database.

0
Subscribe to my newsletter

Read articles from Subrata Ch directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Subrata Ch
Subrata Ch

Software Engineer & Consultant