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,
});
};