리액트 쿼리

김예린·2024년 3월 7일
0

yarn add @tanstack/react-query
yarn add @tanstack/react-query-devtools

설치하고

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { QueryClientProvider, QueryClient } from "@tanstack/react-query";

const queryClient = new QueryClient();

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <QueryClientProvider client={queryClient}>
    <App />
    <ReactQueryDevtools initialIsOpen={false} />
  </QueryClientProvider>
);
<QueryClientProvider client={queryClient}>로 감싼다(쿼리 쓸게요)
<ReactQueryDevtools initialIsOpen={false} /> 는 데브툴스 쓸게요

먼저 인스턴스를 만들어서 서버와 통신하는 부분을 만든다. 여기서는 통신할때 전처리할 게 없지만 그냥 만듬
src>axios>instances.js

import axios from "axios";
export const ServerInstance = axios.create({
  baseURL: process.env.REACT_APP_SERVER_URL,
  headers: {
    "Content-Type": "application/json",
  },
});

TodoForm.jsx

import { useQueryClient, useMutation } from "@tanstack/react-query";
import { useState } from "react";
import { addTodo } from "../apis/mutateFns";
import { v4 as uuidv4 } from "uuid";

const TodoForm = () => {
  const [title, setTitle] = useState("");
  const [body, setBody] = useState("");
  const queryClient = useQueryClient();
  const { mutate: mutateToAdd } = useMutation({
    mutationFn: addTodo,
    onSuccess: async () => {
      console.log("실행됌");
      await queryClient.invalidateQueries(["todos"]);
    },
  });
  const handleSubmit = (e) => {
    e.preventDefault();
    mutateToAdd({
      id: uuidv4(),
      title: title,
      body: body,
      isDone: false,
    });

    setTitle("");
    setBody("");
  };

  return (
    //input..등등 있는 코드 생략
export default TodoForm;

할 일을 입력하는 TodoForm이다.
나는 mutation을 쓰기 위해 mutationFn만 따로 모아놈.

src>apis>mutateFns.js

export const addTodo = async (payload) => {
  await ServerInstance.post("/todos", payload);
};

TodoForm의 useMutation의 mutationFn에서 불러서 사용한다!
addTodo실행되면 db.json에 추가되고 성공하면 invaildateQueries사용해서 무효화시키고 다시 가져와달라고 함 -> 그럼 바로 화면에 나타남ㅋ 간단 ㅋ

TodoList.jsx

import TodoItem from "./Todo";
import { getTodos } from "../apis/queryFns";
import { useQuery } from "@tanstack/react-query";
const TodoList = ({ isActive }) => {
  const { data: todos, isLoading } = useQuery({
    queryKey: ["todos"],
    queryFn: getTodos,
  });
  if (isLoading) {
    return <div>loading...</div>;
  }
  const filteredTodos = todos.filter((todo) => todo.isDone === !isActive) || [];

  return (
    <div>
      <h2>{isActive ? "Working!" : "Done!"}</h2>
      <div className="workingTodo">
        {filteredTodos.map((todo) => {
          return <TodoItem key={todo.id} todo={todo} />;
        })}
      </div>
    </div>
  );
};
export default TodoList;

TodoList에서는 todos의 값을 보여줘야하니까!
useQuery로 값 읽어온다.
useQuery를 이렇게 간단하게 쓸수도있대요

const { data: todos, isLoading } = useQuery(["todos"], getTodos);

queryFn에 쓰는 getTodos는 또 queryFns.js로 나눠놈
src>apis>queryFns.js

import { ServerInstance } from "../axios/instances";
export const getTodos = async () => {
  const { data } = await ServerInstance.get("/todos");
  return data;
};

Todo.jsx
한개의 투두를 다뤄보자!

import { useMutation, useQueryClient } from "@tanstack/react-query";
import { deleteTodo, toggleTodo } from "../apis/mutateFns";

const TodoItem = ({ todo }) => {
  const queryClient = useQueryClient();

  const { title, body, id, isDone } = todo;
  const { mutate: mutateToDelete } = useMutation({
    mutationFn: deleteTodo,
    onSuccess: async () => {
      console.log("삭제실행됌");
      await queryClient.invalidateQueries(["todos"]);
    },
  });
  const { mutate: mutateToToggle } = useMutation({
    mutationFn: toggleTodo,
    onSuccess: async () => {
      console.log("토글실행됌");
      await queryClient.invalidateQueries(["todos"]);
    },
  });
  return (
    <div className="work">
      <h3>{title}</h3>
      <p>{body}</p>
      <div className="button">
        <button onClick={() => mutateToDelete(id)}>삭제</button>
        <button onClick={() => mutateToToggle({ id, isDone })}>
          {isDone ? "취소" : "완료"}
        </button>
      </div>
    </div>
  );
};
export default TodoItem;

queryFns.js에다가 정의했다!!
여기에다 비동기 안걸면 오류난다

export const deleteTodo = async (payload) => {
  await ServerInstance.delete(`/todos/${payload}`);
};
export const toggleTodo = async (payload) => {
  await ServerInstance.patch(`/todos/${payload.id}`, {
    isDone: !payload.isDone,
  });
};
profile
아자아자

0개의 댓글