Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- textContent
- useState
- 템플릿스트링
- 알고리즘
- 부트캠프 #CSS #개발일지 #TIL
- querySelector
- 개발일지 #TIL #프론트엔드 #HTML
- 의사클래스
- 결합선택자
- ㅜㄹㄹ
- 부트캠프 #개발일지 #TIL #FlexboxFroggy #displayflex #flexbox
- 부트캠프 #개발일지 #TIL #Position #위치
- Til
- 깃허브오류
- 부트캠프 #CSS #개발일지 #TIL #박스모델
- 부트캠프 #스파르타코딩클럽 #개발일지# #TIL #Javascript #confirm #location.href
- 리액트
- 부트캠프 #스파르타코딩클럽 #개발일지# #html
- js
- 특성선택자
- 부트캠프 #개발일지 #TIL #CSS속성 #float #clear
- CSS
- 개발일지
- JS예제
- useEffect
- 부트캠프
- React
- appendChild
- 부트캠프 #코딩 #개발일지 #프론트엔드 #CSS #TIL
- 부트캠프 #개발일지 #TIL #그리드 #CSS
Archives
- Today
- Total
나의 개발일지
[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
💡 Remind
이번 과제로 리액트 쿼리를 처음 써봤는데 정말정말 간편하고 좋았다!
타입스크립트도 처음 써보는건데 쿼리로 쓰니까 타입스크립도 간편해졌다..
근데 아직도 타입스크립트는 잘 모르겠어서 더 공부해야 할 것 같다