고양이와 코딩

[React] 친구가 말아준 TodoList 과제 본문

todoList

[React] 친구가 말아준 TodoList 과제

ovovvvvv 2024. 3. 3. 21:23
728x90

뒤늦게 포스팅하는, 친구가 내준 투두리스트 과제!

https://github.com/ovovvvvv/React-Todo

 

GitHub - ovovvvvv/React-Todo: 투두리스트로 배우는 리액트

투두리스트로 배우는 리액트. Contribute to ovovvvvv/React-Todo development by creating an account on GitHub.

github.com

 

 

리액트를 너무 어렵게 생각하는 저를 위해 친구가 과제형식으로 레포지토리를 파 주었습니다 (동기 잘만났다..)

 

 

컴포넌트는 TodoList, TodoItem만 따로 분리했고, 일단 App파일에 대부분의 로직을 작성했습니다!

import { useState, useCallback, useRef, ChangeEvent } from "react";
import TodoList from "./components/TodoList";
import "./App.css";

export interface TodoProps {
  id: number;
  text: string;
  state: boolean;
}

const App: React.FC = () => {
  const [todos, setTodos] = useState<TodoProps[]>([
    {
      id: 0,
      text: "오늘은",
      state: false,
    },
    {
      id: 1,
      text: "초코케익 먹는날",
      state: false,
    },
    {
      id: 2,
      text: "세수하기",
      state: false,
    },
  ]);

  const [inputText, setInputText] = useState("");

  const nextId = useRef<number>(3);

  // useState 생명주기 ?
  const onInsert = useCallback(() => {
    setTodos((prevTodos) => {
      const todo = {
        id: nextId.current,
        text: inputText,
        state: false,
      };
      return [...prevTodos, todo];
    });
    setInputText("");
    nextId.current += 1;
  }, [inputText]);

  const onClick = useCallback(() => {
    onInsert();
  }, [onInsert]);

  const onChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {
    setInputText(e.target.value);
  }, []);

  const handleComplete = useCallback(
    (id: number) => {
      setTodos((prevTodos) =>
        prevTodos.map((todo) =>
          todo.id === id ? { ...todo, state: !todo.state } : todo
        )
      );
    },
    [todos]
  );

  const handleDelete = useCallback(
    (id: number) => {
      setTodos(todos.filter((todo) => todo.id !== id));
    },
    [todos]
  );
  return (
    <div className="container">
      <h1>투두리스트 ~~~ 🍀</h1>

      <input type="text" onChange={onChange} value={inputText} />
      <button type="submit" onClick={onClick}>
        +
      </button>
      <TodoList
        todos={todos}
        handleComplete={handleComplete}
        handleDelete={handleDelete}
      />
    </div>
  );
};

export default App;

 

import TodoItem from "./TodoItem";
import { TodoProps } from "../App";

type HandleCompleteType = (id: number) => void;
type HandleDeleteType = (id: number) => void;

interface TodoListProps {
  todos: TodoProps[];
  handleComplete: HandleCompleteType;
  handleDelete: HandleDeleteType;
}

const TodoList: React.FC<TodoListProps> = ({
  todos,
  handleComplete,
  handleDelete,
}) => {
  return (
    <div className="todoList">
      {todos.map((todo) => (
        <TodoItem
          key={todo.id}
          todo={todo}
          handleDelete={handleDelete}
          handleComplete={handleComplete}
        />
      ))}
    </div>
  );
};

export default TodoList;

 

import { TodoProps } from "../App";

interface TodoItemProps {
  todo: TodoProps;
  handleComplete: (id: number) => void;
  handleDelete: (id: number) => void;
}

const TodoItem: React.FC<TodoItemProps> = ({
  todo,
  handleComplete,
  handleDelete,
}) => {
  const { id, text, state } = todo;

  return (
    <div>
      <li key={id}>
        {text}
        <button onClick={() => handleComplete(id)}>
          {state ? "완료됨" : "미완료"}
        </button>
        <button onClick={() => handleDelete(id)}>삭제</button>
      </li>
    </div>
  );
};

export default TodoItem;

 

이렇게 간단하게 투두 추가, 완료 체크, 삭제 기능을 하는 투두리스트를 만들었습니다

 

 

✔️ 친구의 리뷰

  • useCallBack을 꼭 써야 하는 상황에만 사용하기 
  • 변수명 공식문서에서 권장하는 방식으로 지어라 (handle 어쩌고)
  • useRef를 사용한 이유? (알고 써라)
  • 구조분해할당 사용한 부분은 마음에든다

 

기술이 많이 부족해서 스스로 최대한 이만큼 구현하는데도 꽤 많은 시간이 들다보니,,,
추가구현을 하지 못했고, 컴포넌트도 제대로 분리하지 못했습니다!
다음 포스팅에서는 추가구현 + 컴포넌트 분리와 함께 여유가 된다면 스타일드컴포넌트 사용도 해보려고 합니다!

'todoList' 카테고리의 다른 글

[React] 투두리스트를 만들어보자 ! - 1  (1) 2024.02.14