<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: OGOSHI VALENTINE JOHN</title>
    <description>The latest articles on DEV Community by OGOSHI VALENTINE JOHN (@agyakoji).</description>
    <link>https://dev.to/agyakoji</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1077135%2Fde19ec8d-2081-4500-8e38-d19b76fb1a3f.JPG</url>
      <title>DEV Community: OGOSHI VALENTINE JOHN</title>
      <link>https://dev.to/agyakoji</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/agyakoji"/>
    <language>en</language>
    <item>
      <title>Demystifying Custom Hooks in React: Reusable Stateful Logic</title>
      <dc:creator>OGOSHI VALENTINE JOHN</dc:creator>
      <pubDate>Mon, 22 May 2023 12:48:14 +0000</pubDate>
      <link>https://dev.to/agyakoji/demystifying-custom-hooks-in-react-reusable-stateful-logic-31a5</link>
      <guid>https://dev.to/agyakoji/demystifying-custom-hooks-in-react-reusable-stateful-logic-31a5</guid>
      <description>&lt;p&gt;Demystifying Custom Hooks in React: Reusable Stateful Logic&lt;br&gt;
React is a popular JavaScript library for building user interfaces, and it provides powerful tools like hooks to manage state and lifecycle within components. One of the most useful features in React is custom hooks, which allow developers to extract and reuse stateful logic across multiple components. In this article, we'll dive into the world of custom hooks, understand how they work, and explore their importance in modern React applications.&lt;/p&gt;
&lt;h2&gt;
  
  
  Understanding Custom Hooks
&lt;/h2&gt;

&lt;p&gt;Custom hooks are JavaScript functions that follow a specific naming convention starting with the word "use." These functions can use built-in hooks (such as &lt;code&gt;useState, useEffect,&lt;/code&gt; etc.) or other custom hooks to encapsulate and share stateful logic. Let's take a look at a basic example of a custom hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react';

function useCounter(initialValue) {
  const [count, setCount] = useState(initialValue);

  const increment = () =&amp;gt; {
    setCount((prevCount) =&amp;gt; prevCount + 1);
  };

  return [count, increment];
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code snippet, we define a custom hook called useCounter. This hook uses the useState hook internally to manage a count state and provides an increment function to increase the count value. By convention, custom hooks should return an array, object, or value that can be easily consumed by components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reusability and Separation of Concerns
&lt;/h2&gt;

&lt;p&gt;The primary benefit of custom hooks is code reusability. They enable us to extract and share stateful logic across multiple components without the need for inheritance, render props, or other complex patterns. Let's see how our &lt;code&gt;useCounter&lt;/code&gt; hook can be utilized in different components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function CounterComponent() {
  const [count, increment] = useCounter(0);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;Count: {count}&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={increment}&amp;gt;Increment&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

function AnotherComponent() {
  const [count, increment] = useCounter(10);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;Another count: {count}&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={increment}&amp;gt;Increment&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, both CounterComponent and AnotherComponent are utilizing the useCounter custom hook. This approach allows us to share the same stateful logic for managing count values across multiple components in a simple and consistent manner.&lt;/p&gt;

&lt;p&gt;Custom hooks also promote separation of concerns. By encapsulating specific logic in a custom hook, we can keep our components focused on rendering UI and delegate complex functionality to the hook itself. This improves the readability and maintainability of our codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Composition and Complex Logic
&lt;/h2&gt;

&lt;p&gt;Another powerful aspect of custom hooks is their support for composition. We can combine multiple hooks, including other custom hooks, to create more complex behavior. This enables us to build powerful abstractions on top of existing hooks. Let's consider an example of a custom hook that manages form state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react';

function useForm(initialState) {
  const [values, setValues] = useState(initialState);

  const handleChange = (event) =&amp;gt; {
    const { name, value } = event.target;
    setValues((prevValues) =&amp;gt; ({ ...prevValues, [name]: value }));
  };

  const resetForm = () =&amp;gt; {
    setValues(initialState);
  };

  return { values, handleChange, resetForm };
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, the useForm hook manages the form state and provides the values, handleChange, and resetForm functions. By using this hook, we can easily handle form state management in our components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function MyForm() {
  const { values, handleChange, resetForm } = useForm({ name: '', email: '' });

  const handleSubmit = (event) =&amp;gt; {
    event.preventDefault();
    // Handle form submission
  };

  return (
    &amp;lt;form onSubmit={handleSubmit}&amp;gt;
      &amp;lt;input type="text" name="name" value={values.name} onChange={handleChange} /&amp;gt;
      &amp;lt;input type="email" name="email" value={values.email} onChange={handleChange} /&amp;gt;
      &amp;lt;button type="submit"&amp;gt;Submit&amp;lt;/button&amp;gt;
      &amp;lt;button type="button" onClick={resetForm}&amp;gt;Reset&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
  );
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By composing the &lt;code&gt;useForm&lt;/code&gt; hook, we can easily manage form state, handle form submissions, and reset form values across different components. This composability is a key aspect of custom hooks, allowing us to create reusable and flexible logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Custom Hooks
&lt;/h2&gt;

&lt;p&gt;Testing custom hooks is relatively straightforward since they are regular JavaScript functions. We can write isolated unit tests for them without the need for rendering components. This makes it easier to test the behavior of our custom hooks in isolation, ensuring their correctness and reliability.&lt;/p&gt;

&lt;p&gt;Testing the &lt;code&gt;useCounter&lt;/code&gt; hook from our earlier example might involve verifying that the count state updates correctly when the increment function is called. Similarly, for the &lt;code&gt;useForm&lt;/code&gt; hook, we could write tests to ensure that the &lt;code&gt;handleChange&lt;/code&gt; function correctly updates the form values and that the &lt;code&gt;resetForm&lt;/code&gt; function resets the values to the initial state.&lt;/p&gt;

&lt;p&gt;By testing our custom hooks, we can gain confidence in their behavior and prevent potential bugs when they are used in different components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Custom hooks are a powerful feature in React that enables developers to extract and reuse stateful logic across components. They promote code reusability, separation of concerns, composition, and testability. By leveraging custom hooks, we can build clean, maintainable, and reusable code that facilitates efficient development and reduces code duplication.&lt;/p&gt;

&lt;p&gt;With a solid understanding of custom hooks, you can take advantage of this feature in your React applications and unlock the true potential of code reuse and modularity. Happy coding!&lt;/p&gt;

&lt;p&gt;In this article, we explored the concept of custom hooks in React, learned how to create them, and understood their significance in modern application development. We discussed their reusability, separation of concerns, composition, and testing aspects. Armed with this knowledge, you can now leverage custom hooks to build robust and scalable React applications.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building a Dynamic To-Do List App with React: A Comprehensive Guide</title>
      <dc:creator>OGOSHI VALENTINE JOHN</dc:creator>
      <pubDate>Fri, 19 May 2023 16:27:53 +0000</pubDate>
      <link>https://dev.to/agyakoji/building-a-dynamic-to-do-list-app-with-react-a-comprehensive-guide-4bmi</link>
      <guid>https://dev.to/agyakoji/building-a-dynamic-to-do-list-app-with-react-a-comprehensive-guide-4bmi</guid>
      <description>&lt;p&gt;Are you looking for an efficient way to manage your tasks and improve your productivity? In this article, we will explore how to build a dynamic to-do list app using React, a popular JavaScript library for building user interfaces. We will walk through the code step by step, explaining its functionality and demonstrating how you can customize it to suit your needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we begin, make sure you have the following installed:&lt;br&gt;
Node.js (version 14 or higher)&lt;br&gt;
npm (Node Package Manager)&lt;/p&gt;
&lt;h2&gt;
  
  
  STEP 1: Setting Up the Project
&lt;/h2&gt;

&lt;p&gt;To start, create a new directory for your project and navigate to it in your terminal or command prompt. Run the following command to initialize a new React project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app todo-list-app
cd todo-list-app

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  STEP 2: Installing Dependencies
&lt;/h2&gt;

&lt;p&gt;In this step, we need to install additional dependencies required for our Todo List app. Run the following command to install the required packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install react-toastify react-modal react-toastify

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  STEP 3: Setting up the Component
&lt;/h2&gt;

&lt;p&gt;Open the src directory in your project and create a new file called TodoList.js. This file will contain our main component.&lt;/p&gt;

&lt;p&gt;In the TodoList.js file, import the necessary dependencies and assets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState } from "react";
import { ToastContainer, toast } from 'react-toastify';
import notificationSound from './assets/Best-Reminder.mp3'
import notificationSound2 from './assets/OrchestralEmergencyAlarm.wav'
import 'react-toastify/dist/ReactToastify.css';
import Modal from 'react-modal';

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  STEP 4: Defining the TodoList Component
&lt;/h2&gt;

&lt;p&gt;Inside the TodoList.js file, define a functional component named TodoList using the arrow function syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const TodoList = () =&amp;gt; {
  // Component logic will go here
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  STEP 5: Initializing State Variables
&lt;/h2&gt;

&lt;p&gt;Within the TodoList component, define state variables using the useState hook. These variables will store the tasks, input value, start times, finish times, modal state, edit index, edited value, completed tasks, and snooze times:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [tasks, setTasks] = useState(JSON.parse(localStorage.getItem('tasks')) || []);
const [inputValue, setInputValue] = useState('');
const [startTimes, setStartTimes] = useState({});
const [finishTimes, setFinishTimes] = useState({});
const [modalIsOpen, setModalIsOpen] = useState(false);
const [showHistoryModal, setShowHistoryModal] = useState(false);
const [editIndex, setEditIndex] = useState(-1);
const [editedValue, setEditedValue] = useState('');
const [completedTasks, setCompletedTasks] = useState(JSON.parse(localStorage.getItem('completedTasks')) || []);
const [snoozeTimes, setSnoozeTimes] = useState({});
const audio = new Audio(notificationSound);
const audio2 = new Audio(notificationSound2);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above, we initialize the state variables with the values retrieved from localStorage or default values if no data is available.&lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 6: Configuring the Modal
&lt;/h2&gt;

&lt;p&gt;We will use the Modal component from &lt;code&gt;react-modal&lt;/code&gt; to create a modal dialog for editing tasks. Add the following code to configure the modal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const customStyles = {
  content: {
    top: '50%',
    left: '50%',
    right: 'auto',
    bottom: 'auto',
    marginRight: '-50%',
    transform: 'translate(-50%, -50%)',
    width: '50%',
  },
};

Modal.setAppElement('#root');

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above, we define custom styles for the modal and set the app element for accessibility purposes.&lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 7: Setting up Local Storage Effects
&lt;/h2&gt;

&lt;p&gt;To persist our tasks and completed tasks in local storage, we will use the &lt;code&gt;useEffect&lt;/code&gt; hook. Add the following code to store the tasks and completed tasks whenever they change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  localStorage.setItem('tasks', JSON.stringify(tasks));
}, [tasks]);

useEffect(() =&amp;gt; {
  localStorage.setItem('completedTasks', JSON.stringify(completedTasks));
}, [completedTasks]);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first useEffect will store the tasks in local storage whenever it changes, and the second &lt;code&gt;useEffect&lt;/code&gt; will do the same for the &lt;code&gt;completedTasks.&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 8: Handling Input Change
&lt;/h2&gt;

&lt;p&gt;We need a handler function to update the input value as the user types. Add the following code to define the &lt;code&gt;handleInputChange&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleInputChange = e =&amp;gt; {
  setInputValue(e.target.value);
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  STEP 9: Handling Task Addition
&lt;/h2&gt;

&lt;p&gt;To add a new task, we will define the &lt;code&gt;handleAddTask&lt;/code&gt; function. This function will validate the input, add the task to the tasks array, and display a success or error toast message. Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleAddTask = () =&amp;gt; {
  if (inputValue.trim() !== '') {
    setTasks([...tasks, { id: Date.now(), text: inputValue, completed: false }]);
    setInputValue('');
    setStartTimes({ ...startTimes, [tasks.length]: null });
    setFinishTimes({ ...finishTimes, [tasks.length]: null });

    toast.success(`Task "${inputValue}" added successfully!`, {
      autoClose: 3000,
      position: toast.POSITION.TOP_CENTER,
    });
  } else {
    toast.error('Please enter a task', {
      autoClose: 3000,
      position: toast.POSITION.TOP_CENTER,
    });
  }
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  STEP 10: Handling Task Deletion
&lt;/h2&gt;

&lt;p&gt;To delete a task, we will define the &lt;code&gt;handleDeleteTask&lt;/code&gt; function. This function will remove the task from the tasks array and associated start and finish times. It will also display a success toast message. Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleDeleteTask = (index) =&amp;gt; {
  setTasks(tasks.filter((task, i) =&amp;gt; i !== index));
  const newStartTimes = { ...startTimes };
  const newFinishTimes = { ...finishTimes };
  delete newStartTimes[index];
  delete newFinishTimes[index];
  setStartTimes(newStartTimes);
  setFinishTimes(newFinishTimes);

  toast.success(`Your task has been deleted!`, {
    autoClose: 5000,
    position: toast.POSITION.TOP_CENTER,
  });
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  STEP 11: Handling Task Editing
&lt;/h2&gt;

&lt;p&gt;To edit a task, we will define the &lt;code&gt;handleEditTask&lt;/code&gt; function. This function will set the edit index, pre-fill the modal with the task's current value, and open the modal. Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleEditTask = (index) =&amp;gt; {
  setEditIndex(index);
  setEditedValue(tasks[index].text);
  setModalIsOpen(true);
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  STEP 12: Handling Task Completion
&lt;/h2&gt;

&lt;p&gt;When a task is marked as completed, we will define the &lt;code&gt;handleCompleteTask&lt;/code&gt; function. This function will update the task's completion status, display a success toast message, and move the completed task to the &lt;code&gt;completedTasks&lt;/code&gt; array. Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleCompleteTask = (index) =&amp;gt; {
  const newTasks = [...tasks];
  newTasks[index].completed = true;
  setTasks(newTasks);

  toast.success(`Your task is completed!`, {
    autoClose: 5000,
    position: toast.POSITION.TOP_CENTER,
  });

  // Move the completed tasks to the history
  const completedTask = newTasks[index];
  setCompletedTasks([...completedTasks, completedTask]);
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  STEP 13: Handling Modal Save and Close
&lt;/h2&gt;

&lt;p&gt;For the modal functionality, we need to define the &lt;code&gt;handleModalSave&lt;/code&gt; and &lt;code&gt;handleModalClose&lt;/code&gt; functions. The &lt;code&gt;handleModalSave&lt;/code&gt; function will update the edited task's value and close the modal, while the &lt;code&gt;handleModalClose&lt;/code&gt; function will simply close the modal. Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleModalSave = () =&amp;gt; {
  const newTasks = [...tasks];
  newTasks[editIndex].text = editedValue;
  setTasks(newTasks);
  setModalIsOpen(false);

  toast.success(`Your task has been updated!`, {
    autoClose: 5000,
    position: toast.POSITION.TOP_CENTER,
  });
};

const handleModalClose = () =&amp;gt; {
  setModalIsOpen(false);
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  STEP 14: Handling Start and Finish Times
&lt;/h2&gt;

&lt;p&gt;To set start and finish times for tasks, we will define the &lt;code&gt;handleSetStartTime&lt;/code&gt; and &lt;code&gt;handleSetFinishTime&lt;/code&gt; functions. These functions will update the start and finish times respectively and display success toast messages. Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleSetStartTime = (index, startTime) =&amp;gt; {
  setStartTimes({ ...startTimes, [index]: startTime });
  setSnoozeTimes({ ...snoozeTimes, [index]: startTime });

  toast.success(`Notification successfully set!`, {
    autoClose: 5000,
    position: toast.POSITION.TOP_CENTER,
  });
};

const handleSetFinishTime = (index, finishTime) =&amp;gt; {
  setFinishTimes({ ...finishTimes, [index]: finishTime });

  toast.success(`Notification successfully set!`, {
    autoClose: 5000,
    position: toast.POSITION.TOP_CENTER,
  });
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  STEP 15: Handling Completed Task Deletion
&lt;/h2&gt;

&lt;p&gt;To delete a completed task, we will define the &lt;code&gt;handleDeleteCompletedTask&lt;/code&gt; function. This function will remove the completed task from the &lt;code&gt;completedTasks&lt;/code&gt; array. Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleDeleteCompletedTask = (index) =&amp;gt; {
  setCompletedTasks(completedTasks.filter((completedTask, i) =&amp;gt; i !== index));
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  STEP 16: Handling Snooze
&lt;/h2&gt;

&lt;p&gt;To snooze a task, we will define the &lt;code&gt;handleSnoozeTask&lt;/code&gt; function. This function will set a snooze time for the task and display an info toast message. Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleSnoozeTask = (index, snoozeDuration) =&amp;gt; {
  const now = new Date();
  const snoozeTime = new Date(now.getTime() + snoozeDuration * 60000); // Convert minutes to milliseconds

  setStartTimes({ ...startTimes, [index]: snoozeTime });
  setSnoozeTimes({ ...snoozeTimes, [index]: snoozeTime });

  toast.info(`Task "${tasks[index].text}" snoozed for ${snoozeDuration} minutes!`, {
    autoClose: 5000,
    position: toast.POSITION.TOP_CENTER,
  });
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Snooze Functionality
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;handleSnoozeTask&lt;/code&gt; function is responsible for snoozing a task for a specified duration. When called, it receives the index of the task and the snoozeDuration in minutes. Here's how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get the current date and time using new Date().&lt;/li&gt;
&lt;li&gt;Calculate the snooze time by adding the snooze duration (converted to milliseconds) to the current time.&lt;/li&gt;
&lt;li&gt;Update the startTimes and snoozeTimes state by merging the existing values with the new snooze time using the spread operator (...).&lt;/li&gt;
&lt;li&gt;Display a toast notification using a library like toast.info() to inform the user that the task has been snoozed. The notification includes the task's text and the snooze duration.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  STEP 17: Handling Task Reminders and Alerts
&lt;/h2&gt;

&lt;p&gt;To handle task reminders and alerts, we will use the &lt;code&gt;useEffect&lt;/code&gt; hook. Add the following code to set up the interval:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; useEffect(() =&amp;gt; {
        const intervalID = setInterval(() =&amp;gt; {
            const now = new Date();
            tasks.forEach((task, index) =&amp;gt; {
                if (startTimes[index] &amp;amp;&amp;amp; now &amp;gt;= startTimes[index]) {
                    audio.play();

                    toast.success(`You have two minutes left to start your task: ${task.text}`, {
                        autoClose: 5000,
                        position: toast.POSITION.TOP_CENTER,
                    });

                    setStartTimes({ ...startTimes, [index]: null });
                }

                if (finishTimes[index] &amp;amp;&amp;amp; now &amp;gt;= finishTimes[index]) {
                    audio2.play();
                    toast.warning(`You have 2 minutes left to finish your task: ${task.text}`, {
                        autoClose: 5000,
                        position: toast.POSITION.TOP_CENTER,
                    });

                    setFinishTimes({ ...finishTimes, [index]: null });
                }

                if (snoozeTimes[index] &amp;amp;&amp;amp; now &amp;gt;= snoozeTimes[index]) {
                    audio.play();

                    toast.success(`Time to start your snoozed task: ${task.text}`, {
                        autoClose: 5000,
                        position: toast.POSITION.TOP_CENTER,
                    });

                    setStartTimes({ ...startTimes, [index]: null });
                    setSnoozeTimes({ ...snoozeTimes, [index]: null });
                }
            });
        }, 1000);

        return () =&amp;gt; clearInterval(intervalID);
    }, [tasks, startTimes, finishTimes, snoozeTimes]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Task Notifications
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;useEffect&lt;/code&gt; hook is used to manage task notifications. It sets up a recurring interval (every second) to check the task statuses and display notifications when necessary. Here's how it works:&lt;/p&gt;

&lt;p&gt;When the component mounts or any of the dependencies &lt;code&gt;(tasks, startTimes, finishTimes, or snoozeTimes)&lt;/code&gt; change, the effect is triggered.&lt;/p&gt;

&lt;p&gt;Within the effect, an interval is created using &lt;code&gt;setInterval()&lt;/code&gt; to run the notification logic repeatedly.&lt;/p&gt;

&lt;p&gt;For each task, the following checks are performed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;If the task's start time exists and the current time is greater than or equal to the start time, the notification is triggered using &lt;code&gt;toast.success().&lt;/code&gt; The &lt;code&gt;audio&lt;/code&gt; is played, and the start time for that task is cleared.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the task's finish time exists and the current time is greater than or equal to the finish time, the notification is triggered using &lt;code&gt;toast.warning().&lt;/code&gt; The &lt;code&gt;audio2&lt;/code&gt; is played, and the finish time for that task is cleared.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the task's snooze time exists and the current time is greater than or equal to the snooze time, the notification is triggered using &lt;code&gt;toast.success().&lt;/code&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The audio is played, and both the start time and snooze time for that task are cleared.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, the effect returns a cleanup function that clears the interval using &lt;code&gt;clearInterval()&lt;/code&gt; when the component unmounts or when the dependencies change.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  STEP 18: Rendering the Todo List
&lt;/h2&gt;

&lt;p&gt;In the return statement, we render the JSX for our Todo List app. It consists of a title, an input field for adding tasks, a button to show the completed tasks modal, and a list of tasks. Each task is displayed as an item with buttons to delete, edit, mark as done, set start and finish times, and snooze. The modal dialog is used for editing tasks. The completed tasks are shown in a separate modal dialog.&lt;/p&gt;

&lt;p&gt;At the end of the component, we render the &lt;code&gt;ToastContainer&lt;/code&gt; &lt;code&gt;component from&lt;/code&gt;react-toastify&lt;code&gt;to display toast notifications. Finally, we will render the todo list in the&lt;/code&gt;TodoList` component's JSX. Add the following code:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`&lt;br&gt;
return (&lt;br&gt;&lt;br&gt;
        &lt;/p&gt;
&lt;br&gt;
            &lt;h1&gt;My To-Do List App&lt;/h1&gt;
&lt;br&gt;
            &lt;br&gt;
                &lt;br&gt;
                    &lt;br&gt;
                    Add Task&lt;br&gt;
                    View Completed Tasks&lt;br&gt;
                
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            &amp;lt;ul className="action-buttons"&amp;gt;
                {tasks.map((task, index) =&amp;gt; (
                    &amp;lt;li key={index} style={{ textDecoration: task.completed ? 'Line-Through' : 'none' }}&amp;gt;
                        {task.text}
                        &amp;lt;button className="deleteTask" onClick={() =&amp;gt; handleDeleteTask(index)} style={{ background: 'red' }}&amp;gt;X&amp;lt;/button&amp;gt;
                        &amp;lt;button className="editTask" onClick={() =&amp;gt; handleEditTask(index)} disabled={task.completed} style={{ background: 'blue' }} &amp;gt;Edit&amp;lt;/button&amp;gt;

                        {!task.completed &amp;amp;&amp;amp; (
                            &amp;lt;button onClick={() =&amp;gt; handleCompleteTask(index)} style={{ background: 'green' }}&amp;gt;Done&amp;lt;/button&amp;gt;
                        )}
                        &amp;lt;input type="datetime-local" className="datetime-local" onChange={(e) =&amp;gt; handleSetStartTime(index, new Date(e.target.value))} disabled={task.completed} /&amp;gt;
                        &amp;lt;input type="datetime-local" className="datetime-local" onChange={(e) =&amp;gt; handleSetFinishTime(index, new Date(e.target.value))} disabled={task.completed} /&amp;gt;
                        &amp;lt;button onClick={() =&amp;gt; handleSnoozeTask(index, 1)} disabled={task.completed}&amp;gt;Snooze&amp;lt;/button&amp;gt;
                    &amp;lt;/li&amp;gt;
                ))}

                &amp;lt;Modal isOpen={showHistoryModal} onRequestClose={handleCloseHistoryModal} contentLabel="Completed Tasks" &amp;gt;
                    &amp;lt;div className="history-modal"&amp;gt;
                        &amp;lt;h2 className="historyHeader"&amp;gt;Completed Tasks&amp;lt;/h2&amp;gt;

                        {completedTasks.length &amp;gt; 0 ? (

                        &amp;lt;ul&amp;gt;
                            {completedTasks.map((task, index) =&amp;gt; (
                                &amp;lt;li key={index} className="completedTasks"&amp;gt;
                                    &amp;lt;input className="checkBox" type="checkbox" checked="yes" style={{ background: 'green' }} /&amp;gt;
                                    {task.text}
                                    &amp;lt;button style={{ backgroundColor: 'red'}} onClick={() =&amp;gt; handleDeleteCompletedTask(index)}&amp;gt; X &amp;lt;/button&amp;gt;
                                &amp;lt;/li&amp;gt;
                            ))}
                        &amp;lt;/ul&amp;gt;

                        ) : (
                        &amp;lt;p className="zeroDoneTasks" style={{color: 'black'}}&amp;gt;No completed tasks.&amp;lt;/p&amp;gt;
                        )}

                        &amp;lt;div className="Close-Modal"&amp;gt;
                            &amp;lt;button  onClick={handleCloseHistoryModal}&amp;gt;Close&amp;lt;/button&amp;gt;
                        &amp;lt;/div&amp;gt;

                    &amp;lt;/div&amp;gt;
            &amp;lt;/Modal&amp;gt;

                &amp;lt;Modal isOpen={modalIsOpen} onRequestClose={handleModalClose} style={customStyles}&amp;gt;
                    &amp;lt;h2 className="editTask"&amp;gt;Edit task&amp;lt;/h2&amp;gt;
                    &amp;lt;div className="inputHeader"&amp;gt;
                        &amp;lt;input className="inputMod " type="text" value={editedValue} onChange={(e) =&amp;gt; setEditedValue(e.target.value)} /&amp;gt;
                    &amp;lt;/div&amp;gt;
                    &amp;lt;div className="modalAction"&amp;gt;
                        &amp;lt;button className="modBut" onClick={handleModalSave}&amp;gt;Save&amp;lt;/button&amp;gt;
                        &amp;lt;button className="modBut" onClick={handleModalClose}&amp;gt;Cancel&amp;lt;/button&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/Modal&amp;gt;
            &amp;lt;/ul&amp;gt;
        &amp;lt;/div&amp;gt;


        &amp;lt;ToastContainer /&amp;gt; 
    &amp;lt;/div&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;br&gt;&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 19: Exporting the TodoList Component
&lt;/h2&gt;

&lt;p&gt;At the end of the TodoList.js file, export the &lt;code&gt;TodoList&lt;/code&gt; component:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`&lt;br&gt;
export default TodoList;&lt;/p&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion:
&lt;/h2&gt;

&lt;p&gt;In this article, we have explored the code for building a to-do list app in React. We have seen how to manage tasks using state and local storage, handle user input, and implement features such as add task, view completed tasks, task deletion, editing, completion, setting time notifications and snooze feature. &lt;/p&gt;

&lt;p&gt;We have also utilized the react-toastify library for displaying toast notifications and the react-modal library for implementing modals. By understanding and customizing this code, you can create your own task management application with added features and functionality.&lt;/p&gt;

&lt;p&gt;By leveraging the power of React and the available libraries, you can build robust and interactive applications to enhance task management and productivity in various domains.&lt;br&gt;
Please note that this code assumes you have the required CSS styles and audio files in place. Make sure to update the file paths accordingly or provide your own styles and audio files.&lt;/p&gt;

&lt;p&gt;Good luck with your Todo List app!&lt;/p&gt;

&lt;h1&gt;
  
  
  react #javascript #beginners #reacthooks
&lt;/h1&gt;

</description>
    </item>
  </channel>
</rss>
