3 |
4 | ## 🦉 Main information
5 |
6 | ToDo app is an app that allows users to add, edit, and delete tasks they want to work on. These actions touch upon the four aspects of a CRUD (Create, Read, Update, and Delete) application.
7 |
8 | This application integrate React useState and useEffect Hooks. React Hooks allow for functional components to have a state and use lifecycle methods, allowing you to avoid using class components and have more modular and readable code.
9 |
10 | ToDo app is an excellent app to practice hooks, state, style and data manipulation.
11 |
12 | Here you can find the sourse code with all the necessary and useful comments.
13 |
14 | ## Built With
15 |
16 | [React](https://reactjs.org/) / [JavaScript](https://www.w3schools.com/js/)
17 |
18 | ## ⏲️ Run project
19 |
20 | In the project directory, you can run:
21 |
22 | ### `npm start`
23 |
24 | Runs the app in the development mode.\
25 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
26 |
27 | The page will reload when you make changes.\
28 | You may also see any lint errors in the console.
29 |
30 | ## ⚡ Setup
31 |
32 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
33 |
34 | The following technologies and components were used in this project:
35 |
36 | ### Create React app
37 |
38 | ```
39 | npx create-react-app my-app
40 | cd my-app
41 | npm start
42 | ```
43 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
14 |
15 |
19 |
28 | To Do List
29 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 | import Alert from "./Alert";
3 | import "./App.css";
4 | import ToDo from "./ToDo";
5 | import image from "./todo-image.png";
6 |
7 | // We need to have a localStorage to not lose all values after refreshing the page
8 |
9 | const getLocalStorage = () => {
10 | let list = localStorage.getItem("list");
11 | if (list) {
12 | return JSON.parse(localStorage.getItem("list"));
13 | } else {
14 | return [];
15 | }
16 | };
17 |
18 | function App() {
19 | const [name, setName] = useState(""); // value that we'll use in our form / the empty value by default
20 | const [list, setList] = useState(getLocalStorage()); // empty array that we'll use for local storage // local storage list
21 | const [isEditing, setIsEditing] = useState(false); // a flag in a state whether is editing or not
22 | const [editID, setEditID] = useState(null); // this state will reflect which ite is actually editing
23 | const [alert, setAlert] = useState({
24 | show: false,
25 | msg: "",
26 | type: "",
27 | }); // is an object from we can display alert information
28 |
29 | const handleSubmit = (e) => {
30 | e.preventDefault(); // the preventDefault() method cancels the event if it is cancelable, meaning that the default action that belongs to the event will not occur. // clicking on a "Submit" button, prevent it from submitting a form
31 | // console.log('hello');
32 | if (!name) {
33 | // check if the value in input is empty and if is empty then display the alert
34 | showAlert(true, "danger", "please enter value"); // display alert
35 | } else if (name && isEditing) {
36 | // check if there's something in the value and if the editing is true
37 | setList(
38 | list.map((item) => {
39 | // we have our list and we're iterating over it
40 | if (item.id === editID) {
41 | // if the item Id matches to whatever we have in a state, the return all the propreties
42 | return { ...item, title: name }; // return Id and change the title to whatever is the state
43 | }
44 | return item;
45 | })
46 | );
47 | setName("");
48 | setEditID(null);
49 | setIsEditing(false);
50 | showAlert(true, "success", "value changed");
51 | } else {
52 | // show alert
53 | showAlert(true, "success", "new task added to the list");
54 | const newItem = {
55 | // create a new item is equil to the object with an unique ID and a title tht will be equil to the name value that is coming from the state
56 | id: new Date().getTime().toString(),
57 | title: name,
58 | };
59 | setList([...list, newItem]); // ... get me the previous values from the state add add a new one
60 | setName("");
61 | }
62 | };
63 |
64 | const showAlert = (show = false, type = "", msg = "") => {
65 | // parameters by default
66 | setAlert({ show, type, msg }); // if the property name matches to the variable name that holds the value then show and type an message
67 | };
68 |
69 | const clearList = () => {
70 | showAlert(true, "danger", "empty list");
71 | setList([]);
72 | };
73 |
74 | const removeItem = (id) => {
75 | showAlert(true, "danger", "task removed");
76 | setList(list.filter((item) => item.id !== id)); // list filter always return a new array / if item Id matches to whatever idea passed into remove item, then don't return it from thos filter function. If item Id doesn't match, then it's going to be added to the new array
77 | };
78 |
79 | const editItem = (id) => {
80 | // get a specific item whose Id matches
81 | const specificItem = list.find((item) => item.id === id); // if the item Id matches, then return that item
82 | setIsEditing(true);
83 | setEditID(id);
84 | setName(specificItem.title);
85 | };
86 |
87 | useEffect(() => {
88 | localStorage.setItem("list", JSON.stringify(list));
89 | }, [list]);
90 |
91 | return (
92 | <>
93 |
94 | {/*
To-do list
*/}
95 |
96 |
116 | {list.length > 0 && (
117 |
118 | {" "}
119 | {/* list as a prop into Todo component named 'items' */}
120 |
123 |