src/components/...
TodoList.js
App.js
in order to input dataSystem Properties > Environment Variables > System Variables > Path
. Restart PC.npx create-react-app my-app-name
npx
will not install create-react-app on our system. You can install create-react-app globally on system, but then updates are required, while npx always uses the latest version..
CTRL-SHIFT-P -> Preferences: Open Settings(JSON)
and add:
{
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
}
}
settings.json
and check/add:
"emmet.includeLanguages": {
"javascript": "javascriptreact"
},
{
"workbench.iconTheme": "material-icon-theme",
}
index.js
delete:
// These are used for progressive web app and offline content
import * as serviceWorker from '.serviceWorker';
...
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
index.css
logo.svg
and from App.js
delete:
import logo from '.logo.svg';
...
// And <header>..</header> with everything inside it, keep only return(<div ClassName="App"></div>);
App.css
(or delete it completely and remove import)src/components/...
todo-app/src
called components
, and create these files:
../src/components/TodoAddForm.js
../src/components/TodoItem.js
../src/components/TodoList.js
App.css
, add:
```cssheader, form { min-height: 15vh; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; } form input, form button { padding: 0.5rem; font-size: 2rem; border: none; background: white; } form button { color: #17cbff; background: #f7fffe; cursor: pointer; transition: all 0.3s ease; } form button:hover { background: #0095bf; color: white; } .todo-container { display: flex; justify-content: center; align-items: center; }
.todo-list { min-width: 30%; list-style: none; }
.todo { margin: 0.5rem; background: white; font-size: 1.5rem; color: black; display: flex; justify-content: space-between; align-items: center; transition: all 1s ease; } .filter-todo { padding: 1rem; } .todo li { flex: 1; }
.trash-btn, .complete-btn { background: #f35252; color: white; border: none; padding: 1rem; cursor: pointer; font-size: 1rem; } .complete-btn { background: #18edfe; } .todo-item { padding: 0rem 0.5rem; }
.fa-trash, .fa-check { pointer-events: none; }
.fall { transform: translateY(10rem) rotateZ(20deg); opacity: 0; }
.completed { text-decoration: line-through; opacity: 0.5; }
/*CUSTOM SELECTOR */ select { -webkit-appearance: none; -moz-appearance: none; -ms-appearance: none; appearance: none; outline: 0; box-shadow: none; border: 0 !important; background-image: none; }
/* Custom Select / .select { margin: 1rem; position: relative; overflow: hidden; } select { color: #00394a; font-family: “Poppins”, sans-serif; cursor: pointer; width: 12rem; } / Arrow */ .select::after { content: “\25BC”; position: absolute; top: 0; right: 0; padding: 1rem; background: #17cbff; cursor: pointer; pointer-events: none; }
.select:hover::after { background: #0095bf; color: white; transition: all 0.3s ease; }
- In `/public/index.html/` add in `<head>`:
```html
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.1/css/all.min.css"
integrity="sha256-mmgLkCYLUQbXn0B1SRqzHar6dCnv9oZFPEC1g1cwlkk="
crossorigin="anonymous"
/>
); };
export default TodoAddForm;
- Hook TodoAddForm.js to the App.js. In `App.js` by importing and adding `<TodoAddForm />`:
```js
import React from "react";
import "./App.css";
import TodoAddForm from "./components/TodoAddForm";
function App() {
return (
<div className="App">
<header>
<h1>ToDo List. Yay.</h1>
</header>
<TodoAddForm />
</div>
);
}
TodoList.js
import React from "react";
const TodoList = ({ todos, setTodos, filteredTodos }) => {
return (
<div className="todo-container">
<ul className="todo-list">
</ul>
</div>
);
};
export default TodoList;
App.js
and hook it on function App()
:
import TodoList from "./components/TodoList";
...
function App() {
return (
<div className="App">
<header>
<h1>ToDo List. Yay.</h1>
</header>
<TodoAddForm />
<TodoList />
</div>
);
}
App.js
in order to input dataimport React, { useState } from "react";
function App() {
const [inputText, setInputText] = useState("");
const [todos, setTodos] = useState([]);
...
return (
<div className="App">
<header>
<h1>ToDo List. Yay.</h1>
</header>
<TodoAddForm
inputText={inputText}
setInputText={setInputText}
todos={todos}
setTodos={setTodos}
/>
</div>
TodoAddForm.js
:
```js
const TodoAddForm = ({ setInputText, todos, setTodos, inputText }) => {
const inputTextHandler = (e) => {
// console.log(e.target.value);
setInputText(e.target.value);
};
const submitTodoHandler = (e) => {
e.preventDefault(); // Prevent page from refreshing on submit
if (inputText !== “”) {
setTodos([
…todos,
{
id: Math.floor(Math.random() * 1000),
text: inputText,
completed: false,
},
]);
}
setInputText(“”);
};
…
return (
);
- Now every time we write in our for and hit the + button, a new state will be created (see with React Chrome Extension)
## <a name="workshowtodos"></a>Show todos in browser/UI (render them) + Complete and Delete
- In `TodoAddForm.js`, add `value={inputText}`:
```js
return (
<form>
<input
value={inputText}
onChange={inputTextHandler}
type="text"
className="todo-input"
/>
};
TodoList.js
:
```js
import React from “react”;
import TodoItem from “./TodoItem”;const TodoList = ({ todos, setTodos, filteredTodos }) => { return ( <div className="todo-container"> <ul className="todo-list"> {filteredTodos.map((todo) => ( <TodoItem setTodos={setTodos} todos={todos} key={todo.id} text={todo.text} id={todo.id} todo={todo} /> ))} </ul> </div> ); };
export default TodoList;
- And create `TodoItem.js` and add:
```js
import React from "react";
const TodoItem = ({ text, todo, setTodos, todos }) => {
const deleteHandler = () => {
setTodos(todos.filter((el) => el.id !== todo.id));
};
const completeHandler = () => {
setTodos(
todos.map((item) => {
if (item.id === todo.id) {
return {
...item,
completed: !item.completed,
};
}
return item;
})
);
};
return (
<div className="todo">
<li className={`todo-item ${todo.completed ? "completed" : ""}`}>
{text}
</li>
<button onClick={completeHandler} className="complete-btn">
<i className="fas fa-check"></i>
</button>
<button onClick={deleteHandler} className="trash-btn">
<i className="fas fa-trash"></i>
</button>
</div>
);
};
export default TodoItem;
App.js
:
return (
<div className="App">
...
<TodoList
setTodos={setTodos}
todos={todos}
filteredTodos={filteredTodos}
/>
</div>
);
}
import React from "react";
const TodoAddForm = ({
setInputText,
todos,
setTodos,
inputText,
setStatus,
}) => {
// JavaScript functions
const inputTextHandler = (e) => {
// console.log(e.target.value);
setInputText(e.target.value);
};
const submitTodoHandler = (e) => {
e.preventDefault();
if (inputText !== "") {
setTodos([
...todos,
{
id: Math.floor(Math.random() * 1000),
text: inputText,
completed: false,
},
]);
}
setInputText("");
};
const statusHandler = (e) => {
setStatus(e.target.value);
};
// Render HTML
return (
<form>
<input
value={inputText}
onChange={inputTextHandler}
type="text"
className="todo-input"
/>
<button onClick={submitTodoHandler} className="todo-button" type="submit">
<i className="fas fa-plus-square"></i>
</button>
<div className="select">
<select onChange={statusHandler} name="todos" className="filter-todo">
<option value="all">All</option>
<option value="completed">Completed</option>
<option value="uncompleted">Uncompleted</option>
</select>
</div>
</form>
);
};
export default TodoAddForm;
import React from "react";
import TodoItem from "./TodoItem";
const TodoList = ({ todos, setTodos, filteredTodos }) => {
return (
<div className="todo-container">
<ul className="todo-list">
{filteredTodos.map((todo) => (
<TodoItem
setTodos={setTodos}
todos={todos}
key={todo.id}
text={todo.text}
id={todo.id}
todo={todo}
/>
))}
</ul>
</div>
);
};
export default TodoList;
import React from "react";
const TodoItem = ({ text, todo, setTodos, todos }) => {
const deleteHandler = () => {
setTodos(todos.filter((el) => el.id !== todo.id));
};
const completeHandler = () => {
setTodos(
todos.map((item) => {
if (item.id === todo.id) {
return {
...item,
completed: !item.completed,
};
}
return item;
})
);
};
return (
<div className="todo">
<li className={`todo-item ${todo.completed ? "completed" : ""}`}>
{text}
</li>
<button onClick={completeHandler} className="complete-btn">
<i className="fas fa-check"></i>
</button>
<button onClick={deleteHandler} className="trash-btn">
<i className="fas fa-trash"></i>
</button>
</div>
);
};
export default TodoItem;
import React, { useState, useEffect } from "react";
import "./App.css";
import TodoAddForm from "./components/TodoAddForm";
import TodoList from "./components/TodoList";
function App() {
const [inputText, setInputText] = useState("");
const [todos, setTodos] = useState([]);
const [status, setStatus] = useState("all");
const [filteredTodos, setFilteredTodos] = useState([]);
const filterHandler = () => {
switch (status) {
case "completed":
setFilteredTodos(todos.filter((todo) => todo.completed === true));
break;
case "uncompleted":
setFilteredTodos(todos.filter((todo) => todo.completed === false));
break;
default:
setFilteredTodos(todos);
break;
}
};
// Save to local (browser cache)
const saveLocalTodos = () => {
localStorage.setItem("todos", JSON.stringify(todos));
};
const getLocalTodos = () => {
if (localStorage.getItem("todos") !== null) {
let todoLocal = JSON.parse(localStorage.getItem("todos"));
setTodos(todoLocal);
}
};
useEffect(() => {
getLocalTodos(); // function that runs once when the app starts
}, []);
useEffect(() => {
filterHandler();
saveLocalTodos();
}, [todos, status]); // function that runs every time "todos" changes
return (
<div className="App">
<header>
<h1>ToDo List. Yay.</h1>
</header>
<TodoAddForm
inputText={inputText}
todos={todos}
setTodos={setTodos}
setInputText={setInputText}
setStatus={setStatus}
/>
<TodoList
setTodos={setTodos}
todos={todos}
filteredTodos={filteredTodos}
/>
</div>
);
}
export default App;
package.json
add:
"homepage": ".",
npm run build
build
is created, now you can create a GitHub repository and follow the steps there (or down bellow) in order to push your build to the new repository.
# On GitHub.com website:
# Create a new repository (write name & description)
# (optional) Create a Readme.MD file
# On CLI (locally):
# Open the terminal in that folder/project's path
# Write the following commands:
git init
git remote add origin https://github.com/username/projectname/.git
git remote -v
git pull origin master # needed to update the commit history of new repo (especially if Readme.MD or LICENSE was created)
git status
git add -A
git status
git commit -m "Initial commit from local project"
git push origin master
[Build A Todo App With REACT | React Project For Beginners](https://www.youtube.com/watch?v=pCA4qpQDZD8&ab_channel=DevEd) from Dev Ed |