카테고리 없음

react-query 실무

홍순2 2024. 3. 7. 00:32

 
백엔드에 저장된 데이터를 변경하면 Tanstack쿼리는 자동으로 변경이 이루어진다. 
 
리액트쿼리는 응답 데이터를 캐시 처리한다 이전 useEffect와 fetch를 이용할때는 새요청을 전송해서 모든 데이터를 다시 가져왔어야 했는데(화면에 로딩 스피너가 뜨면서 1초후에 데이터를 보여준다.) 리액트 쿼리를 사용하면 그전에 했던 수고를 덜고 데이터를 즉각적으로 제공되면서 로딩중 로딩 스피너가 뜨지 않고 바로바로보여준다. 
 

slow 3g로 설정을 하고 화면에는 업데이트된 데이터가 즉각 표시된다.

 

signal - 요청을 취소할 때 필요하다. 예를 들어 요청이 완료되기전에 사용자가 페이지에서 나가는 경우 요청중지 할때 signal이 쓰인다. 지금은 검색을 안하기때문에 리액트 쿼리를 비활성화 할 필요가 있다.

 

import { useRef, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { fetchEvents } from "../../util/http";
import LoadingIndicator from "../UI/LoadingIndicator";
import ErrorBlock from "../UI/ErrorBlock";
import EventItem from "./EventItem";

export default function FindEventSection() {
  const searchElement = useRef();
  const [searchTerm, setSearchTerm] = useState();

  const { data, isLoading, isError, error } = useQuery({
    queryKey: [
      "events",
      { search: searchTerm },
    ] /*검색어와 일치하는 이벤트만 가져옴 */,
    queryFn: ({ signal }) =>
      fetchEvents({
        signal,
        searchTerm,
      }) /*리액트 쿼리는 fetchEvents에 객체를 전달하고 이 객체에 signal과 searchTerm이라는 프로퍼티를 설정 */,
    enabled: searchTerm !== undefined /* 쿼리 비활성화 */,
  });

QueryFunctionContext( Query Functions | TanStack Query Docs )는 쿼리 함수에 전달되는 객체이다 객체안에 signal 속성을 객체구조 분해할당을 해서 취소신호를 전달할것이다.리액트 쿼리 커스텀 훅안에 queryFn:  ({signal})객체를  화살표 함수를 통해 =>  fetchEvents 함수로 전달한다. fetchEvents인자에 ({signal,searchTerm)}을 키-값으로 설정하였다.
 
잠깐!!! 여기서 객체 구조분해란 객체로부터 속성을 해체하여 객체의 원래 속성명과는 다른 이름의 변수에 할당할 수 있는것이다 리액트에서 props 객체구조 분해는 부모 components에서 객체 구조분해 한 것을 자식 components props로 전달해준다.

구조분해할당 예시 

let cart = {product: "Book", price: 30000};
let {product, price} = cart 
console.log(product) // Book
console.log(price) // 30000

 

fetchEvents 함수는 전달받은 {signal, searchTerm(검색상태 useState())}객체를 props 구조분해할당으로 함수 인자에넣고 내장된 fetch()의 두번째 인수에 넣어서 취소신호를 전달한다.

 
 
 
 

web dev로 검색을 했는데 제목에는 web dev가 없지만 설명에는 단어가 포함되어 있어서 유효한 결과를 보여준다. 그 이유는 검색어를 searchTerm을 useState상태로 관리하고 있기 때문 그래서 상태가 바뀔때마다 다시 실행되면서 리액트 쿼리는 검색어별로 다른 http요청을 전송한다.

 
 

그런데 검색어를 입력하지 않았는데 두개의 events 쿼리키가 실행되고 있어서 불필요하다. 그래서 검색어를 입력하지 않을 때는 enabled로 비활성화 해야한다.

 

검색 searchTerm의 상태가 undefined이면 검색리액트 쿼리를 비활성화 하여 events쿼리키가 중복 실행되지 않는다.

 
 

콘솔에 찍힌 signal 비활성화 상태를 확인해 보니 취소 신호가 잘 전달되었다.

 

검색창에 검색을 하지 않을 때 로딩스피너 표시가 뜨지 않는다 isPending대신 isLoading을 넣었기 때문이다. 둘의 차이는 isLoading의 쿼리가 비활성화 됐다고 해서 True가 되지 않는다