NextJS로 Todo 앱 만들기
시사
안녕하세요.
오늘은 NextJS 및 SASS을 사용하여 작은 할 일 앱을 빌드하는 방법을 보여 드리겠습니다. 피드백이 있으면 댓글에 남겨주세요.
직접 시도해 볼 수 있습니다: Live Demo
코드 링크
파비안반디니 / todo-앱-튜토리얼
dev.to에 있는 튜토리얼의 소스 코드
튜토리얼 소스 코드
데모: https://todo-app-tutorial-f4p029hcs-fabianbandini.vercel.app/
View on GitHub
프로젝트 초기화
mkdir todo-app
cd todo-app
npm init -y
npm install sass next react react-dom
패키지.json 변경
{
"name": "todo-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev":"next dev"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"next": "^0.0.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"sass": "^1.53.0"
}
}
마지막으로 콘솔에
npm run dev
를 입력하고 브라우저에서 localhost으로 이동합니다.파일 구조 만들기
todo 앱용 로직 만들기
스타일/global.scss
* {
font-family: sans-serif;
padding: 0;
margin: 0;
background: #1A1B1E;
}
페이지/_app.js
import "../styles/global.scss";
export default function App({Component, pageProps}){
return (
<Component {...pageProps} />
);
}
구성 요소/TodoList.js
export default function TodoList(){
return (
<>
</>
);
}
이 구성 요소는 사용자의 입력을 처리하고 새 작업을 생성합니다.
지금은 구성 요소만 만들 것입니다. 로직이 구현된 후 일부 스타일을 추가합니다.
구성 요소/TodoItem.js
import {useState} from "react";
export default function TodoItem({title, id, handleClickRemove}){
const [done, setIsDone] = useState(false);
const markDone = () => {
setIsDone(!done);
}
return (
<div onClick={markDone}>
<h2>{title}</h2>
<button onClick={() => handleClickRemove(id)}></button>
</div>
);
}
위에서 본 구성 요소는 우리의 할 일을 모델링하는 데 주의를 기울일 것입니다. TodoList.js로 돌아가서 todo를 추가하고 그에 따라 표시하는 논리를 만듭니다.
구성 요소/TodoList.js
import {useState} from "react";
import TodoItem from "./TodoItem";
export default function TodoList() {
const [todos, setTodos] = useState([]);
const [currentInput, setCurrentInput] = useState("");
const handleClickAdd = (e) => {
e.preventDefault();
if (currentInput === "") {
//input validation
return;
}
const newTodo = {
id: currentInput + Math.random().toString(),
content: currentInput
}
setTodos([newTodo, ...todos]);
setCurrentInput("")
}
const handleClickRemove = (id) => {
const filteredTodos = todos.filter(todo => todo.id !== id);
setTodos(filteredTodos);
}
return (
<div>
<form onSubmit={(e) => handleClickAdd(e)}>
<input onChange={(e) =>
setCurrentInput(e.target.value)}
value={currentInput}/>
<button type={"submit"}>add</button>
</form>
<div>
{
todos.map(todo => {
return (
<TodoItem title={todo.content}
id={todo.id}
handleClickRemove=
{handleClickRemove}/>
);
})
}
</div>
</div>
);
}
todos를 조금 더 보기 좋게 만들기 위해 css를 추가하기 전에 삭제 아이콘을 추가합니다. 내 here에서 얻을 수 있습니다.
구성 요소/TodoItem.js
import {useState} from "react";
import Image from "next/image";
export default function TodoItem({title, id, handleClickRemove}){
const [done, setIsDone] = useState(false);
const markDone = () => {
setIsDone(!done);
}
return (
<div onClick={markDone}>
<h2>{title}</h2>
<button onClick={() => handleClickRemove(id)}>
<Image src={"/trashicon.svg"}
width={20} height={20} /></button>
</div>
);
}
이제 우리는 재미있는 부분에 도달하고 실제로 작은 사이트의 스타일을 지정할 것입니다.
페이지/index.js
import TodoList from "../components/TodoList";
import styles from "./index.module.scss";
export default function IndexPage(){
return (
<div className={styles.container}>
<h1>Todo List</h1>
<TodoList />
</div>
);
}
페이지/index.module.scss
.container {
position: absolute;
left: 50%;
transform: translate(-50%, 0);
margin-top: 10em;
h1 {
color: white;
margin-bottom: 2em;
}
}
구성 요소/TodoList.js
import {useState} from "react";
import TodoItem from "./TodoItem";
import styles from "./todolist.module.scss";
export default function TodoList() {
const [todos, setTodos] = useState([]);
const [currentInput, setCurrentInput] = useState("");
const handleClickAdd = (e) => {
e.preventDefault();
if (currentInput === "") {
//input validation
return;
}
const newTodo = {
id: currentInput + Math.random().toString(),
content: currentInput
}
let _todos = todos;
_todos.push(newTodo);
setTodos(_todos)
setCurrentInput("")
}
const handleClickRemove = (id) => {
const filteredTodos = todos.filter(todo => todo.id !== id);
setTodos(filteredTodos);
}
return (
<div className={styles.container}>
<form onSubmit={(e) => handleClickAdd(e)}>
<input onChange={(e) =>
setCurrentInput(e.target.value)}
value={currentInput}
placeholder={"todo..."}/>
<button type={"submit"}>add</button>
</form>
<div className={styles.todos}>
{
todos.map(todo => {
return (
<TodoItem title={todo.content}
id={todo.id}
handleClickRemove
={handleClickRemove}/>
);
})
}
</div>
</div>
);
}
구성 요소/TodoList.module.scss
.container {
display: flex;
flex-direction: column;
row-gap: 2em;
form {
display: flex;
column-gap: 2em;
input {
background: #2C2E33;
border: none;
height: 40px;
width: 250px;
border-radius: 10px;
color: white;
padding-left: 1em;
}
input:focus {
outline: 2px solid #47428E;
}
button {
width: 100px;
border: none;
background: #47428E;
border-radius: 10px;
color: white;
}
button:hover {
transition: 0.3s;
background: #3f3a7c;
}
}
.todos {
display: flex;
flex-direction: column;
row-gap: 1em;
}
}
구성 요소/TodoItem.js
import {useState} from "react";
import Image from "next/image";
import styles from "./todoitem.module.scss";
export default function TodoItem({title, id, handleClickRemove}) {
const [done, setIsDone] = useState(false);
const markDone = () => {
setIsDone(!done);
}
return (
<div onClick={markDone}
className={done? styles.container:
styles.doneContainer}
<h2>{title}</h2>
<button onClick={() => handleClickRemove(id)}>
<Image src={"/trashicon.svg"}
width={20} height={20}/>
</button>
</div>
);
}
구성 요소/todoitem.module.scss
.container {
background: #2C2E33;
border-radius: 10px;
display: flex;
justify-content: space-between;
padding: 0.5em 1em 0.5em 1em;
align-items: center;
h2 {
color: white;
font-size: 20px;
font-weight: lighter;
}
button {
background: #ce6767;
height: 40px;
width: 40px;
border: none;
border-radius: 10px;
}
}
.doneContainer {
background: #535761;
border-radius: 10px;
display: flex;
justify-content: space-between;
padding: 0.5em 1em 0.5em 1em;
align-items: center;
h2 {
color: #2b2d31;
text-decoration: line-through;
font-size: 20px;
font-weight: lighter;
}
button {
display:none;
}
}
오늘은 여기까지입니다. 이 작은 앱을 재미있게 만드셨기를 바랍니다. 당신이 그것을 즐겼다면 좋아요를 남겨주세요.
Reference
이 문제에 관하여(NextJS로 Todo 앱 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/fabianbandini/create-a-todo-app-with-nextjs-1274텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)