나의 개발일지

[TypeScript] 개인과제 - TypeScript버전으로 react-query를 이용하여 TodoList 만들기 본문

과제 및 팀프로젝트

[TypeScript] 개인과제 - TypeScript버전으로 react-query를 이용하여 TodoList 만들기

heew0n 2023. 12. 19. 20:57

🔥 TypeScript  개인과제 🔥

 

TypeScript버전으로 react-query를 이용하여 TodoList 만들기

 

<필수 구현 사항> (모든 구현 사항은 Typescript로 작성돼야 한다)

  • Todo 항목 추가 하기

        -  사용자가 새로운 Todo 항목을 입력하고 추가 할 수 있는 기능.

 

  • Todo 항목 목록 표시 기능

        -   각 Todo 하목은 고유 식별자를 가짐

 

  • Todo 삭제 하기

        -   삭제 시 사용자에게 삭제 확인 요청

 

  • Todo 완료 상태 표시 기능

        -   사용자가 Todo 항목을 완료했음을 표시한다

 

 

 

 


 

 

 

src > api > todos.ts

import axios from "axios";

// 조회
const getTodos = async (): Promise<any> => {
  try {
    const response = await axios.get(
      `${process.env.REACT_APP_SERVER_URL}/todos`
    );

    console.log("get", response.data);
    return response.data;
  } catch (error) {
    throw error;
  }
};

// 추가
const addTodo = async (newTodo: any): Promise<void> => {
  try {
    const response = await axios.post(
      `${process.env.REACT_APP_SERVER_URL}/todos`,
      newTodo
    );
    console.log("ADD", response.data);
  } catch (error) {}
};

//삭제
const deleteTodo = async (id: string): Promise<void> => {
  try {
    await axios.delete(`${process.env.REACT_APP_SERVER_URL}/todos/${id}`);
  } catch (error) {}
};

// 스위치
const switchTodo = async ({
  id,
  isDone,
}: {
  id: string;
  isDone: boolean;
}): Promise<void> => {
  try {
    await axios.patch(`${process.env.REACT_APP_SERVER_URL}/todos/${id}`, {
      isDone,
    });
  } catch (error) {}
};
export { getTodos, addTodo, deleteTodo, switchTodo };

 

 

 

 

 

src > components> Input.tsx

import React, { useState } from "react";
import { StInput, StBtn, StFormWrapper } from "./style";
import uuid from "react-uuid";
import { useMutation, useQueryClient } from "react-query";
import { addTodo } from "../../api/todos";

export interface TList {
  id: string;
  title: string;
  content: string;
  isDone: boolean;
}

const Input = () => {
  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");

  const queryClient = useQueryClient();
  const mutation = useMutation(addTodo, {
    onSuccess: () => {
      queryClient.invalidateQueries("todos");
    },
  });

  const onTitleChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    setTitle(e.target.value);
  };
  const onContentChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    setContent(e.target.value);
  };

  const onSubmitHandler = (e: React.FormEvent<HTMLFormElement>): void => {
    if (title === "" && content === "") {
      alert("내용을 입력해주세요");
      return;
    }
    e.preventDefault();
    const newTodo: TList = {
      id: uuid(),
      title,
      content,
      isDone: false,
    };
    mutation.mutate(newTodo);

    setTitle("");
    setContent("");
  };

  return (
    <div>
      <StFormWrapper onSubmit={onSubmitHandler}>
        <StInput
          type="text"
          value={title}
          onChange={onTitleChangeHandler}
          autoFocus
        />
        <StInput
          type="text"
          value={content}
          onChange={onContentChangeHandler}
        />
        <StBtn type="submit">등 록</StBtn>
      </StFormWrapper>
    </div>
  );
};

export default Input;

 

 

 

 

 

src > components> TodoList.tsx

import { deleteTodo, getTodos, switchTodo } from "../../api/todos";
import { useMutation, useQuery, useQueryClient } from "react-query";
import type { TList } from "../Input/Input";
import {
  StTodoListWrapper,
  StTodoContainer,
  StTodo,
  StBtns,
  StBtn,
  StTitle,
  StContent,
  StHaveToDoAndDone,
} from "./style";

const TodoList = () => {
  const { isLoading, isError, data } = useQuery<TList[]>("todos", getTodos);
  console.log("data", data);

  const queryClient = useQueryClient();
  const deleteMutation = useMutation(deleteTodo, {
    onSuccess: () => {
      queryClient.invalidateQueries("todos");
    },
  });
  const updateMutation = useMutation(switchTodo, {
    onSuccess: () => {
      queryClient.invalidateQueries("todos");
    },
  });

  // 삭제 핸들러
  const onDeleteHandler = (id: string) => {
    deleteMutation.mutate(id);
  };

  // 스위치 핸들러
  const onSwitchHandler = (id: string, isDone: boolean) => {
    updateMutation.mutate({ id, isDone: !isDone });
  };

  if (isLoading) {
    return <p>로딩중입니다</p>;
  }

  if (isError || !data) {
    return <p>에러가 발생하였습니다</p>;
  }

  return (
    <StTodoListWrapper>
      <StHaveToDoAndDone>Thing to do</StHaveToDoAndDone>
      <StTodoContainer>
        {data
          .filter((item) => item.isDone === false)
          .map((todo) => (
            <StTodo>
              <div key={todo.id}>
                <StTitle>{todo.title}</StTitle>
                <StContent>{todo.content}</StContent>
                <StBtns>
                  <StBtn onClick={() => onSwitchHandler(todo.id, todo.isDone)}>
                    완 료
                  </StBtn>
                  <StBtn onClick={() => onDeleteHandler(todo.id)}>삭 제</StBtn>
                </StBtns>
              </div>
            </StTodo>
          ))}
      </StTodoContainer>
      <StHaveToDoAndDone>Work done</StHaveToDoAndDone>
      <StTodoContainer>
        {data
          .filter((item) => item.isDone === true)
          .map((todo) => (
            <StTodo>
              <div key={todo.id}>
                <StTitle>{todo.title}</StTitle>
                <StContent>{todo.content}</StContent>
                <StBtns>
                  <StBtn onClick={() => onSwitchHandler(todo.id, todo.isDone)}>
                    취 소
                  </StBtn>
                  <StBtn onClick={() => onDeleteHandler(todo.id)}>삭 제</StBtn>
                </StBtns>
              </div>
            </StTodo>
          ))}
      </StTodoContainer>
    </StTodoListWrapper>
  );
};

export default TodoList;

 

 

 

 

💡 프로젝트 소개

프로젝트명 : TypeScript를 기반으로 한 react-query로 TodoList 만들기
개발 기간 : 2023.12.12-2023.12.16

 

 

 

 

 

💡 화면구성

 

Header & Input

 

 

 


 

TodoList > Thing to do

 

 

 

 


 

 


TodoList > Work Done & Footer

 

 

 

 

 

💡 깃헙 주소

https://github.com/heeneeee/React_todoList_TS/tree/level5

 

GitHub - heeneeee/React_todoList_TS

Contribute to heeneeee/React_todoList_TS development by creating an account on GitHub.

github.com

 

 

 

 

💡 Remind

이번 과제로 리액트 쿼리를 처음 써봤는데 정말정말 간편하고 좋았다! 

타입스크립트도 처음 써보는건데 쿼리로 쓰니까 타입스크립도 간편해졌다..

근데 아직도 타입스크립트는 잘 모르겠어서 더 공부해야 할 것 같다