항해/TIL

TIL(3/5) / react-query로 todolist 리팩토링

yeeendy 2024. 3. 5. 23:57

api 세팅

// src/api/todos.js
import axios from "axios";

const getTodos = async () => {
  const response = await axios.get(`${process.env.REACT_APP_SERVER_URL}/todos`);
  return response.data;
};

const addTodo = async (newTodo) => {
  await axios.post(`${process.env.REACT_APP_SERVER_URL}/todos`, newTodo);
};

const removeTodo = async (id) => {
  await axios.delete(`${process.env.REACT_APP_SERVER_URL}/todos/${id}`);
};

const switchTodo = async (payload) => {
  await axios.patch(
    `${process.env.REACT_APP_SERVER_URL}/todos/${payload.id}`,
    payload
  );
};

export { getTodos, addTodo, removeTodo, switchTodo };

getTodos는 return문이 꼭 있어야 하고 나머지는 변경하는 역할 이기에 return문을 쓰지않아도 된다.

 

getTodos

import React from "react";
import Todo from "../Todo";
import { getTodos } from "../../../api/todos";
import { useQuery } from "react-query";

function TodoList({ isActive }) {

  const { isLoading, isError, data } = useQuery("todos", getTodos);

  if (isLoading) {
    return <h1>로딩 중입니다!</h1>;
  }
  if (isError) {
    return <h1>에러 발생!</h1>;
  }
  return (
    <StyledDiv>
      <StyledTodoListHeader>
        {isActive ? "해야 할 일 ⛱" : "완료한 일 ✅"}
      </StyledTodoListHeader>
      <StyledTodoListBox>
        {data
          .filter((item) => item.isDone === !isActive)
          .map((item) => {
            return <Todo key={item.id} todo={item} isActive={isActive} />;
          })}
      </StyledTodoListBox>
    </StyledDiv>
  );
}

export default TodoList;

addTodo

// Input.jsx

const queryClient = useQueryClient();

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

 const { data } = useQuery("todos", getTodos);
  
(...)

mutation.mutate(newTodo);

removeTodo, switchTodo

import { useMutation, useQueryClient } from "react-query";
import { removeTodo, switchTodo } from "../../../api/todos";

function Todo({ todo, isActive }) {
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const removeMutation = useMutation(removeTodo, {
    onSuccess: () => {
      queryClient.invalidateQueries("todos");
    },
  });
  const switchMutation = useMutation(switchTodo, {
    onSuccess: () => {
      queryClient.invalidateQueries("todos");
    },
  });
  // 완료, 취소를 handling하는 함수
  const handleSwitchButton = () => {
    const updatedTodo = {
      id: todo.id,
      isDone: !todo.isDone,
    };
    switchMutation.mutate(updatedTodo);
  };

  // [삭제] 버튼 선택 시 호출되는 함수(user의 confirmation 필요)
  const handleRemoveButton = () => {
    if (window.confirm(CONFIRM_MESSAGE)) {
      removeMutation.mutate(todo.id);
    }
  };

  // [상세보기]를 선택하는 경우 이동하는 함수
  const handleDetailPageLinkClick = () => {
    navigate(`/${todo.id}`);
  };

  return (
    <StyledDiv>
      <FlexTitleBox>
        <StyledTitle>{todo.title}</StyledTitle>
        <LinkedP onClick={handleDetailPageLinkClick}>[상세보기]</LinkedP>
      </FlexTitleBox>
      <HeightBox height={10} />
      <StyledContents>{todo.contents}</StyledContents>
      <HeightBox height={20} />
      <FlexButtonBox>
        <TodoButton onClick={handleSwitchButton}>
          {isActive ? "완료" : "취소"}
        </TodoButton>
        <TodoButton onClick={handleRemoveButton}>삭제</TodoButton>
      </FlexButtonBox>
    </StyledDiv>
  );
}

export default Todo;

'항해 > TIL' 카테고리의 다른 글

TIL(3/7) / level5 과제 중 에러들  (0) 2024.03.07
TIL(3/6) / aws s3 액세스 키 발급  (0) 2024.03.07
TIL(3/2) / CSR, SSR  (0) 2024.03.02
TIL(2/29) / lv3  (0) 2024.02.29
TIL(2/28) / React Query  (0) 2024.02.28