Skip to content

Feat: 투두리스트 기능 구현 #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open

Feat: 투두리스트 기능 구현 #2

wants to merge 31 commits into from

Conversation

makepin2r
Copy link
Collaborator

@makepin2r makepin2r commented Jul 17, 2025

투두리스트 기능 구현

변경 사항

  • 리스트 페이지 (HomePage)
    • 투두 생성 form (CreateTodoBox)
    • 투두 리스트 컴포넌트 (TodoList)
      • 투두 요소 (TodoItem)에서 완료 여부 토글, 수정 페이지 이동, 삭제 가능
  • 투두 수정 페이지 (TodoPage)
    • 투두 수정 form (ModifyTodoBox)
  • 투두리스트 커스텀 훅 (useTodos) 생성
    • 마운트 시 localStorage의 데이터를 state로 가져와 CRUD 관리
    • 언마운트 시 state의 최종 업데이트 사항을 localStorage에 반영
    • loading 상태, 투두 생성, 투두 리스트 조회, id별 개별 투두 조회, 완료 여부 토글, 투두 내용 수정, 투두 삭제 기능 구현

기타

  • 제가 편의상 별 생각 없이 Vite를 써버렸습니다.
    그런데 생각해보니 이 과제에서 굳이 Vite를 쓸 필요가 없었고, 더욱이 Jest는 공식적으론 Vite 환경에서의 사용을 비추천하고 있네요.
    리서치를 먼저 하고 세팅했어야 하는데 죄송합니다.
    Vite 사용이 과제 범위에 어긋난다면 다시 세팅해서 올릴게요!

@makepin2r makepin2r self-assigned this Jul 17, 2025
@makepin2r makepin2r requested a review from f-lab-stella July 17, 2025 13:52
Comment on lines 14 to 35
const handleSubmit = (e: SyntheticEvent) => {
e.preventDefault();

const form = e.target as HTMLFormElement;
const titleInput = form.elements.namedItem("title") as HTMLInputElement;
const descInput = form.elements.namedItem(
"description"
) as HTMLInputElement;

if (e.target) {
const newTodo: Omit<Todo, "id" | "createdAt" | "completed"> = {
title: titleInput.value ?? "",
description: descInput.value ?? "",
};

onCreate(newTodo);

titleInput.value = "";
descInput.value = "";
} else {
alert("등록에 실패했습니다.");
}
Copy link

@f-lab-stella f-lab-stella Jul 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

form구조가 복잡하지는 않아 보이는데, unontrolled로 작성하신 이유가 있으실까요 ~?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

controlled 방식을 의도하고 작성하진 않았습니다!
사실 dom에서 직접 값을 받아서 쓰는 방식이라서 uncontrolled라고 생각했어요.
어떤 점에서 controlled 방식이 되는 건지 좀더 말씀해주실 수 있나요?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

state사용해서 작성하고, 성능상의 이슈나, 복잡한 폼일 경우 uncontrolled로 작성하긴 합니다.

@makepin2r makepin2r requested a review from f-lab-stella July 18, 2025 10:32
Copy link

const handleUpdate = (e: SyntheticEvent) => {
e.preventDefault();

if (e.target || !params.id) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (e.target || !params.id) {
if (!e.target || !params.id) {

@makepin2r
Copy link
Collaborator Author

추가 코멘트

@@ -1,4 +1,4 @@
import { PAGE_SIZE } from "@/components/pagintaion-box";
export const PAGE_SIZE = 5;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

페이지네이션 UI에 PAGE_SIZE를 정의하는 게 맞지 않다 느껴져 유틸 쪽으로 옮겼습니다.
아직 상수가 많진 않아 모아두려구요!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/constants/index.ts 파일에 추후에는 분리하면 더 좋을 것 같아요

import { Todo, NewTodo } from "@/types/todo-type";

const ModifyTodoBox = () => {
const params = useParams();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고치다 보니, route로 들어오는 값을 UI 컴포넌트에서 검사하는 게 적절하지 않을 수 있을 것 같습니다.
멘토님 의견이 궁금합니다!

페이지 컴포넌트에서 params.id를 검사하고, ModifyTodoBox에 props로 전달하는 게 어떨까 싶었습니다.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

params 의 값이 채워지기 전까지 로딩을 띄운다던지 요런 조건부 렌더링이 필요해보입니다. 👍

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (!params) {
 return <Loading />
} else {
 ..
 
 return <ModifyTodoBox />
}


const LOCAL_STORAGE_KEY = "todos";
const useTodos = () => {
const [todos, setTodos] = useState<Todo[] | null>(null);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Todo는 id값을 가지고 있으니 업데이트시 id를 활용하는 방법으로 리팩토링해보면 어떨까 싶습니다!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants