TodoList ReFactoring
1. 폴더구성
- 원장튜터님께 내가 작성한 코드 리뷰를 부탁드렸는데, 보완할 점과 아쉬운 부분들을 말씀해주시고 그에 대해 수정을 한 번 해보라고 숙제를 내주셨다.
- 그 중 하나가 폴더구성을 깔끔하게 바꾸는 것이었는데 컴포넌트를 다시 짜보았다.
- CSS 적용을 위해 폴더로 나누어 주었다.
- 각 폴더에는 jsx, css 파일이 있는데 폴더안 jsx에서 사용한 것들만 css로 적용했다.
- 자식 컴포넌트 파일은 하위폴더로 지정해주었다.
2. App.jsx
3. App.css
- css를 나눠주고 App.css에 모든 파일들을 import 하는 형식을 썼다.
@import url("./components/TodoHeader/TodoHeader.css");
@import url("./components/TodoBoard/TodoInput/TodoInput.css");
@import url("./components/TodoBoard/TodoList/TodoList.css");
@import url("./components/TodoBoard/TodoList/TodoItem/TodoItem.css");
.wrap {
max-width: 1200px;
min-height: 800px;
margin: 0 auto;
}
5. TodoBoard.jsx
- 이 파일에서 수정된 부분은 TodoList 부분을 컴포넌트로 나누어준 것이다.
- 컴포넌트를 만들고 자식 파일에
props
를 보내주었다.
import React, { useEffect, useState } from "react";
import TodoItem from "./TodoList/TodoItem/TodoItem";
import TodoInput from "./TodoInput/TodoInput";
import TodoList from "./TodoList/TodoList";
export default function TodoBoard() {
const [todos, setTodos] = useState([]);
useEffect(() => {
fetch("db/todo.json")
.then((res) => res.json())
.then((data) => setTodos(data));
}, []);
const deleteTodoHandler = (id) => {
const newTodoList = todos.filter((todo) => todo.id !== id);
setTodos(newTodoList);
};
return (
<div>
<TodoInput todos={todos} setTodos={setTodos} />
<TodoList
todos={todos}
deleteTodoHandler={deleteTodoHandler}
setTodos={setTodos}
isWorking={true}
/>
<TodoList
todos={todos}
deleteTodoHandler={deleteTodoHandler}
setTodos={setTodos}
isWorking={false}
/>
</div>
);
}
6.TodoList.jsx
- 전에 없었던 완전히 새로 만든 파일이다.
- isWorking 이라는
props
를 받아와 true
면 "Working.. 🔥" false
면 "Done..🎉" 을 화면에 출력해준다.
- 원장님이 내주신 숙제
- map을 돌린 후 삼항 연산자로 화면을 나타내기 전에 filter로 한 번 걸러주기
- todo.isDone
true
면 isWorking 에 출력
- todo.isDone
false
면 Done 에 출력
- 맨 처음에 에러가 떴는데 맵 뒤에도 삼항연산자를 써서 그랬다.
import React from "react";
import TodoItem from "./TodoItem/TodoItem";
export default function TodoList({
todos,
deleteTodoHandler,
setTodos,
isWorking,
}) {
return (
<div>
<h1>{isWorking ? "Working.. 🔥" : "Done..🎉"}</h1>
<div className="wrap-list">
{todos
.filter((todo) => (todo.isDone ? isWorking : !isWorking))
.map((todo) => (
<TodoItem
key={todo.id}
id={todo.id}
title={todo.title}
text={todo.text}
isdone={todo.isDone}
deleteTodoHandler={deleteTodoHandler}
todos={todos}
setTodos={setTodos}
/>
))}
</div>
</div>
);
}
7. TodoItem
- 아이디를
uuidv4()
로 랜덤 생성해주니 숫자가 아닌 문자열이 되었다.
- 그 부분을
Number()
가 아닌 toString()
로 수정해주니 정상 작동하였다.
const changeIsDone = (event) => {
const newTodos = [];
todos.forEach((todo) => {
console.log(todo);
if (todo.id.toString() === event.target.value) {
newTodos.push({ ...todo, isDone: !todo.isDone });
} else {
newTodos.push({ ...todo });
}
});
setTodos(newTodos);
- 아이디를 생성할때
uuidv4()
형식을 사용하는 것으로 수정하였다.
- 사용방법 : 터미널에서
npm add uuid
- 제목이나 내용이 빈 칸이거나 아무 내용없이 띄어쓰기만 했다면 경고문을 작동
import React, { useState } from "react";
import { v4 as uuidv4 } from "uuid";
export default function TodoInput({ todos, setTodos }) {
const [titleValue, setTitleValue] = useState("");
const [textValue, setTextValue] = useState("");
const onsubmit = (e) => {
e.preventDefault();
const newTodo = {
id: uuidv4(),
title: titleValue,
text: textValue,
isDone: true,
};
if (titleValue.trim() === "" || textValue.trim() === "")
return alert("빈 칸을 채워주세요.");
setTodos([...todos, newTodo]);
setTitleValue("");
setTextValue("");
};
return (
<form className="form" onSubmit={onsubmit}>
<div className="form-input">
<label className="form-label" htmlFor="title">
제목{" "}
</label>
<input
className="input"
id="title"
value={titleValue}
type="text"
onChange={(event) => setTitleValue(event.target.value)}
/>
<label className="form-label" htmlFor="text">
내용{" "}
</label>
<input
className="input"
id="text"
value={textValue}
type="text"
onChange={(event) => setTextValue(event.target.value)}
/>
</div>
<button className="form-button">Click</button>
</form>
);
}
9. 느낀점
- 내가 원했던 것이 이렇게 깔끔하게 컴포넌트를 나누는 것이었는데 코드리뷰를 받길 잘했다고 생각한다.
= 그런데 저것도 깔끔하게 나눈 것인지 지금보니 불문명하다.
- 원장님이 내주신 숙제 덕분에 더 성장한 것을 느낀다.
- 강의에서 본 내용을 활용할 수 있어서 좋았다.
trim
메서드 사용^^