Tanstack Query

gimmari·2024년 9월 23일
0

📝 React

목록 보기
24/24
post-thumbnail

01. 컴포넌트 마운트 시(useEffect) 처리

(1)-1. 데이터 패칭하기

useEffect hook을 사용하여 컴포넌트가 마운트될 때 비동기 요청을 통해 데이터를 가져오는 방식

useEffect(() => {
  const fetchData = async () => {
    const result = await axios("https://api.example.com/data");
    setData(result.data);
  };
  fetchData();
}, []);

(1)-2. 로딩 및 에러 처리

import React, { useState, useEffect } from "react";
import axios from "axios";

const App = () => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      setLoading(true);
      try {
        const response = await axios.get("http://localhost:4000/todos");
        setData(response.data);
      } catch (error) {
        setError(error);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      <h1>Fetched Data</h1>
      <ul>
        {data &&
          data.map((item) => (
            <li key={item.id}>
              <h2>{item.title}</h2>
              <p>{item.isDone ? "Done" : "Not Done"}</p>
            </li>
          ))}
      </ul>
    </div>
  );
};

export default App;
  • 상태 관리의 복잡성
  • 중복된 코드
    각 컴포넌트마다 동일한 비동기 로직을 반복해서 작성
  • 비즈니스 로직의 분리 부족
    비즈니스 로직과 UI 로직이 혼합
  • 서버 상태 관리의 어려움 ☝ 서버 상태 vs 클라이언트 상태란?
    `클라이언트 상태`는 UI 관련된 일시적인 데이터(예: 폼 입력값)를 의미합니다. 반면에 `서버 상태`는 서버에서 가져오는 데이터(예: API 응답)를 포함하며, 캐싱, 동기화, 재검증(revalidate) 등의 복잡한 관리가 필요합니다.

02. TanStack Query (대안)

사용방법 - useQuery

  • (시작하기 전) 세팅
    • 프로젝트 생성
      yarn create vite tanstack-query-app --template react
    • 설치
      yarn add @tanstack/react-query
    • 적용할 범위(ex : 전역)에 Provider를 이용하여 적용
      // main.jsx
      
      import ReactDOM from "react-dom/client";
      import App from "./App.jsx";
      import "./index.css";
      import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
      
      const queryClient = new QueryClient();
      
      ReactDOM.createRoot(document.getElementById("root")).render(
        <QueryClientProvider client={queryClient}>
          <App />
        </QueryClientProvider>
      );
  • useQuery의 개념
    - useQuery는 데이터를 가져오기 위해 사용되는 TanStack Query의 대표적인 훅. 쿼리 키비동기 함수(패칭 함수)를 인자로 받아 데이터를 가져오고, 로딩 상태, 오류 상태, 그리고 데이터를 반환합니다.
    import { useQuery } from "@tanstack/react-query";
    import axios from "axios";

사용방법 - useMutation

  • useMutation의 주요 개념

    • useMutation은 데이터를 생성, 수정, 삭제하는 등의 작업에 사용되는 훅입니다. CUD에 대한 비동기 작업을 쉽게 수행하고, 성공 또는 실패 시에 추가적인 작업을 실행
    • 비동기 작업을 쉽게 처리한다는 말 안에는 작업이 완료된 후에 관련된 쿼리를 무효화하는 과정 => 최신 데이터를 유지하는 데에 필수적인 요소
  • useMutation 기본 사용법

    const App = () => {
      const fetchTodos = async () => {
        const response = await axios.get("http://localhost:4000/todos");
        return response.data;
      };
    
      const {
        data: todos,
        isPending,
        isError,
      } = useQuery({
        queryKey: ["todos"],
        queryFn: fetchTodos,
      });
    
      if (isPending) {
        return <div>로딩중입니다...</div>;
      }
    
      if (isError) {
        return <div>데이터 조회 중 오류가 발생했습니다.</div>;
      }
    
      return (
        <div>
          <h3>TanStack Query</h3>
          <ul>
            {todos.map((todo) => {
              return (
                <li
                  key={todo.id}
                  style={{
                    display: "flex",
                    alignItems: "center",
                    gap: "10px",
                    backgroundColor: "aliceblue",
                  }}
                >
                  <h4>{todo.title}</h4>
                  <p>{todo.isDone ? "Done" : "Not Done"}</p>
                </li>
              );
            })}
          </ul>
        </div>
      );
    };
    
    export default App;
    

    사용방법 - invalidateQueries

  • invalidateQueries의 개념

    • invalidateQueries는 특정 쿼리를 무효화하여 데이터를 다시 패칭하게 하는 함수입니다. 주로 useMutation과 함께 사용하여 데이터가 변경된 후 관련 쿼리를 다시 가져오도록 합니다.
    • 이를 통해 데이터가 항상 최신 상태로 유지될 수 있도록 도와줍니다. 예를 들어, 새로운 할 일을 추가한 후 기존의 할 일 목록을 다시 가져오도록 할 수 있습니다.

  • invalidateQueries 기본 사용법

    invalidateQueries 로직 추가

    import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import axios from "axios";
import { useState } from "react";

const App = () => {
  const queryClient = useQueryClient();

  const [todoItem, setTodoItem] = useState("");

  const fetchTodos = async () => {
    const response = await axios.get("http://localhost:4000/todos");
    return response.data;
  };

  const addTodo = async (newTodo) => {
    await axios.post("http://localhost:4000/todos", newTodo);
  };

  const {
    data: todos,
    isPending,
    isError,
  } = useQuery({
    queryKey: ["todos"],
    queryFn: fetchTodos,
  });

  const { mutate } = useMutation({
    mutationFn: addTodo,
    onSuccess: () => {
      // alert("데이터 삽입이 성공했습니다.");
      queryClient.invalidateQueries(["todos"]);
    },
  });

  if (isPending) {
    return <div>로딩중입니다...</div>;
  }

  if (isError) {
    return <div>데이터 조회 중 오류가 발생했습니다.</div>;
  }

  return (
    <div>
      <h3>TanStack Query</h3>
      <form
        onSubmit={(e) => {
          e.preventDefault();

          const newTodoObj = { title: todoItem, isDone: false };

          // useMutation 로직 필요
          mutate(newTodoObj);
        }}
      >
        <input
          type="text"
          value={todoItem}
          onChange={(e) => setTodoItem(e.target.value)}
        />
        <button>추가</button>
      </form>
      <ul>
        {todos.map((todo) => {
          return (
            <li
              key={todo.id}
              style={{
                display: "flex",
                alignItems: "center",
                gap: "10px",
                backgroundColor: "aliceblue",
              }}
            >
              <h4>{todo.title}</h4>
              <p>{todo.isDone ? "Done" : "Not Done"}</p>
            </li>
          );
        })}
      </ul>
    </div>
  );
};

export default App;
profile
김마리의 개발.로그

0개의 댓글