• 티스토리 홈
  • 프로필사진
    redpome
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
redpome
  • 프로필사진
    redpome
    • 분류 전체보기 (50)
      • 내일배움캠프 (23)
      • 웹개발 지식 (2)
      • 프로그래머스 (8)
      • React (7)
      • 코딩테스트 (1)
      • UI-UX (1)
      • 타입스크립트 (2)
      • Next.js (3)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • 타입 스크립트 기초 - (2)
        2025년 03월 07일
        • redpome
        • 작성자
        • 2025.03.07.:43

        https://redpome.tistory.com/39

         

        타입스크립트 기초 -( 1 )

        Vite을 통해 React+Typescript 조합으로 타입스크립트 기초를 배우자 타입 명시import Name from "./components/Name.tsx";const App = () => { return ( );};export default App; 처음 만들 때 생성되는 App 컴포넌트에서 위와

        redpome.tistory.com

         

        이전 내용에 이어서 작성한다, CRUD에서 Delete와 Update를 다룬다.

         


          const handleDeleteTodo = async (id: Todo["id"]) => {
            fetch(`http://localhost:5000/todos/${id}`, {
              method: "DELETE",
            });
            setTodoList((prev) => prev.filter((todo) => todo.id !== id));
          };

         

        먼저 id로 할 일을 구분하면서 삭제하는 핸들러를 위와 같이 정의하였다.

        인자에 특정 타입을 정해주기 위해 Todo["id"]라는 타입을 지정한 것이다.

         

        ...
              <TodoList todoList={todoList} onDeleteClick={handleDeleteTodo} />
        ...
        
        type TodoListProps = {
        ...
          onDeleteClick: (id: Todo["id"]) => void;
        };
        ...
        function TodoList({ todoList, onDeleteClick }: TodoListProps) {
        ...
              {todoList.map((todo) => (
                <TodoItem key={todo.id} {...todo} onDeleteClick={onDeleteClick} /> 
        ...
        type TodoItemProps = Todo & { onDeleteClick: (id: Todo["id"]) => void };
        
        function TodoItem({ id, title, completed, onDeleteClick }: TodoItemProps) {
          return (
          
        ...
              <button onClick={() => onDeleteClick}>삭제</button>
        ...

         

        삭제 버튼에 onClick이벤트에 onDeleteClick을 넘겨줘야하므로 TodoItem 컴포넌트에 onDeleteClick 인자를 넣었다.

        이때 TodoItemProps에서 Todo["id"]에 해당하는 인자의 타입을 받고 onDeleteClick 콜백에서 아무것도 반환하지 않으므로 void를 반환하도록 명시했다.

         

        TodoList는 중간에 있는 컴포넌트이니까 일단 위와 같이 쓰고 넘어간다.

         

        최상위 부모 컴포넌트에서는 이젠 핸들러를 onDeleteClick에 직접 넘겨주고있다.

         


         

        Update

        completed의 값을 변경할 수 있는 로직은 다음과 같다.

         

        type ToggleTodo = Omit<Todo, "title">;

         

        먼저 위와 같은 타입을 지정했다. id와 title을 제외한 completed 타입을 제외하고 써야하므로 핸들러에서 다음과 같이 작성한다.

         

        const handleToggleTodo = async ({ id, completed }: ToggleTodo) => {
          await fetch(`http://localhost:5000/todos/${id}`, {
            method: "PATCH",
            body: JSON.stringify({ completed: !completed }),
          });
        
          setTodoList((prev) =>
            prev.map((todo) => {
              if (todo.id === id) {
                return {
                  ...todo,
                  // 완료 상태를 반전
                  completd: !completed,
                };
              }
              return todo;
            }),
          );
        };

         

        인자로 넘겨주는 id, completed의 타입을 지정할 때 Omit을 이용하여 필요한 인자의 타입만을 명시했다.

        이후에는 삭제 함수와 마찬가지로 컴포넌트에 Props로 전달해준다.

         


        import "./App.css";
        import { type Todo, getTodos } from "./components/todos";
        import { useState, useEffect } from "react";
        
        type ToggleTodo = Omit<Todo, "title">;
        function App() {
          const [todoList, setTodoList] = useState<Todo[]>([]);
          useEffect(() => {
            getTodos().then((data) => setTodoList(data));
          }, []);
        
          const [title, setTitle] = useState("");
          const handleTitleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
            setTitle(e.target.value);
          };
          const handleAddTodo = async () => {
            const newTodo: Todo = {
              id: crypto.randomUUID(),
              title,
              completed: false,
            };
        
            await fetch("http://localhost:5000/todos", {
              method: "POST",
              body: JSON.stringify(newTodo),
            });
        
            setTodoList((prev) => [...prev, newTodo]);
            setTitle("");
          };
        
          const handleDeleteTodo = async (id: Todo["id"]) => {
            fetch(`http://localhost:5000/todos/${id}`, {
              method: "DELETE",
            });
            setTodoList((prev) => prev.filter((todo) => todo.id !== id));
          };
        
          const handleToggleTodo = async ({ id, completed }: ToggleTodo) => {
            await fetch(`http://localhost:5000/todos/${id}`, {
              method: "PATCH",
              body: JSON.stringify({ completed: !completed }),
            });
            setTodoList((prev) =>
              prev.map((todo) => {
                if (todo.id === id) {
                  return {
                    ...todo,
                    completed: !completed,
                  };
                }
                return todo;
              }),
            );
          };
        
          return (
            <>
              <TodoList
                todoList={todoList}
                onDeleteClick={handleDeleteTodo}
                onToggleClick={handleToggleTodo}
              />
              <input type="text" value={title} onChange={handleTitleChange} />
              <button onClick={handleAddTodo}>입력</button>
            </>
          );
        }
        type TodoListProps = {
          todoList: Todo[];
          onDeleteClick: (id: Todo["id"]) => void;
          onToggleClick: (toggleTodo: ToggleTodo) => void;
        };
        
        function TodoList({ todoList, onDeleteClick, onToggleClick }: TodoListProps) {
          return (
            <>
              {todoList.map((todo) => (
                <TodoItem
                  key={todo.id}
                  {...todo}
                  onDeleteClick={onDeleteClick}
                  onToggleClick={onToggleClick}
                />
              ))}
            </>
          );
        }
        
        type TodoItemProps = Todo & {
          onDeleteClick: (id: Todo["id"]) => void;
          onToggleClick: (toggleTodo: ToggleTodo) => void;
        };
        
        function TodoItem({
          id,
          title,
          completed,
          onDeleteClick,
          onToggleClick,
        }: TodoItemProps) {
          return (
            <div>
              <br></br>
              <div>id:{id}</div>
              <div onClick={() => onToggleClick({ id, completed })}>title:{title}</div>
              <div>completed:{completed}</div>
              <button onClick={() => onDeleteClick(id)}>삭제</button>
              <br></br>
            </div>
          );
        }
        
        export default App;

        '타입스크립트' 카테고리의 다른 글

        타입스크립트 기초 -( 1 )  (0) 2025.03.06
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바