[ React-query ] setQueryData, getQueryData, inValidateQuries

exceed_96·2024년 1월 22일
0

React-Query

목록 보기
9/9
post-thumbnail

최근에 했던 프로젝트에 리액트 쿼리를 활용하려고 했으나 흐지부지 쓰지 못했던게 아쉬워서 다음 프로젝트에서는 제대로 사용하려고 공부하기 위한 리액트 쿼리 정리이다.


mutation으로 데이터를 업데이트 했을 때 캐시에 있는 데이터는 어떻게 업데이트할 수 있을까?

대표적으로 2가지 방법이 있다.

invalidateQuries

setQueryData

이번 섹션에서는 위 2가지 메서드에 대해서 알아보자



1. inValidateQuries

inValidateQuery는 현재 캐싱된 데이터를 무효화시키고 새로운 데이터를 가져오게 하는 메서드이다.

즉, post요청을 통해서 서버의 데이터를 업데이트 했을 경우 기존에 있던 캐시 데이터를 무효화시켜서 서버에서 새로운 데이터를 받아와 서버와 클라이언트의 데이터를 동일하게 만들고 최신으로 유지시킬 수 있는 것이다.

하지만 해당 메서드는 서버에서 다시 데이터를 받아오는 작업을 하므로 데이터가 많아진다면 사용자 경험 측면에서 데이터를 버리고 서버에서 다시 받아오는 과정이 답답하게 느껴질 수 있다는 단점이 있다.



1.1 inValidateQuery 사용법

await queryClient.invalidateQueries({
  queryKey: ['posts'],
  exact,
  refetchType: 'active',
}, { throwOnError, cancelRefetch })
  • queryKey
    무효화 시킬 키

  • refetchType
    해당 데이터가 어떤 상태인지에 따라서 서버에서 데이터를 다시 받아오는지를 결정할 수 있다.

    • active
      해당 캐시 데이터가 active상태일 때 useQuery백그라운드에서 해당 데이터를 다시 가져온다.
    • inactive
      해당 캐시 데이터가 inactive상태일 때 useQuery백그라운드에서 해당 데이터를 다시 가져온다.
    • all
      해당 캐시 데이터가 어떤 상태이던지 useQuery백그라운드에서 해당 데이터를 다시 가져온다.
    • none
      해당 쿼리가 어떤 상태이던지 해당 데이터를 다시 가져오지 않는다.
  • options

    • throwOnError
      • 해당 데이터를 다시 가져오던 중 에러가 발생하면 해당 메서드가 발동된다.
      • 기본값은 true이다.
    • cancelRefetch
      • 현재 실행 중인 요청이 있다면 새 요청을 실행하기 전에 취소한다.
      • false로 할 경우 이미 실행중인 요청이 있다면 새 요청 실행을 취소한다.


1.2 inValidateQuries 사용예시

import { useState } from "react";
import Main from "../Component/Main/Main";
import User from "../Component/User/User";
import { useQueryClient } from "@tanstack/react-query";

const MainComponent = () => {
  const [main, setMain] = useState(false);
  const queryClient = useQueryClient();

  const componentRouterHandler = () => {
    queryClient.invalidateQueries({
      queryKey: ["user"],
      refetchType: "all",
    });
    setMain((previousState) => !previousState);
  };

  return (
    <>
      {main ? <Main /> : <User />}
      {queryClient.getQueryData(["age"]) ? (
        <p>{queryClient.getQueryData(["age"])}</p>
      ) : (
        <p>no info</p>
      )}
      <button onClick={componentRouterHandler}>router button</button>
    </>
  );
};

원래는 mutation으로 데이터를 업데이트 할 때 쓰지만 이번 예시에는 버튼을 누를 때마다 해당 inValidateQuries를 통해서 해당 키를 무효화 시키는 작업을 해봤다.

queryKey의 값으로 "user"를 넣으면 버튼을 누를 때마다 "user"키의 데이터가 무효화되어지고 해당 키를 서버에서 다시 받아오게 된다.

refetchType의 값으로 "all"을 정의하면 해당 키가 어떤 상태인지 상관없이 무조건 데이터를 서버에서 다시 받아오게 된다.



2. setQueryData

setQueryData는 캐시 데이터를 수동으로 설정하는 메서드이다.

서버에서 데이터를 다시 가져오는 inValidateQuries와는 달리 쿼리 데이터를 클라이언트에서 바꿔주는 메서드이다.

서버와 클라이언트의 데이터가 실시간으로 동기화되고 있지는 않지만 네트워크 요청을 기다릴 피룡가 없어서 사용자 경험에서는 데이터를 업데이트 할 시 자연스러운 데이터 변환을 경험할 수 있다.



2.1 setQueryData 사용법

queryClient.setQueryData(queryKey, updater)
  • queryKey
    • 수동으로 업데이트 할 쿼리 데이터의 키를 정의한다.
  • updater
    • 어떤 데이터로 업데이트 할 건지 정의할 수 잇다.
    • 특정 값이 아닌 함수를 updater에 정의할 수 있다.
      • 만약 함수가 undefined를 반환한다면 쿼리 데이터는 업데이트 하지 않는다.


2.2 setQueryData 사용예시

import { useState } from "react";
import Main from "../Component/Main/Main";
import User from "../Component/User/User";
import { useQueryClient } from "@tanstack/react-query";

const MainComponent = () => {
  const [main, setMain] = useState(false);
  const queryClient = useQueryClient();

  const componentRouterHandler = () => {
    queryClient.setQueryData(["age"], "29");
    setMain((previousState) => !previousState);
  };

  return (
    <>
      {main ? <Main /> : <User />}
      {queryClient.getQueryData(["age"]) ? (
        <p>{queryClient.getQueryData(["age"])}</p>
      ) : (
        <p>no info</p>
      )}
      <button onClick={componentRouterHandler}>router button</button>
    </>
  );
};

export default MainComponent;

이번에는 버튼을 누를때마다 setQueryData메서드를 실행시켜서 "age"키를 생성하여 29 라는 값을 넣어줄 것이다.

위와같이 버튼을 누를 때마다 "age"키가 캐시에 생성되었고 해당 값으로 29가 들어간걸 확인할 수 있다.





const componentRouterHandler = () => {
    queryClient.setQueryData(["age"], undefined);
    setMain((previousState) => !previousState);
};

undefined값을 넣으면 해당 값은 캐시에 저장이 되지 않는걸 확인할 수 있다.



3. getQueryData

getQueryData캐시에 저장된 데이터를 가져오는 메서드이다.

사실 해당 메서드는 생각 안하고 있었는데 캐시를 정의한걸 어떻게 가져올수 있을까? 를 생각해보다가 찾은 메서드라 정리해본다.



3.1 getQueryData 사용법

const data = queryClient.getQueryData(queryKey)

queryKey에 해당하는 데이터가 없다면 undefined를 반환한다.



3.2 getQueryData 사용예시

import { useState } from "react";
import Main from "../Component/Main/Main";
import User from "../Component/User/User";
import { useQueryClient } from "@tanstack/react-query";

const MainComponent = () => {
  const [main, setMain] = useState(false);
  const queryClient = useQueryClient();

  const componentRouterHandler = () => {
    queryClient.setQueryData(["age"], 29);
    setMain((previousState) => !previousState);
  };

  return (
    <>
      {main ? <Main /> : <User />}
      {queryClient.getQueryData(["age"]) ? (
        <p>{queryClient.getQueryData(["age"])}</p>
      ) : (
        <p>no info</p>
      )}
      <button onClick={componentRouterHandler}>router button</button>
    </>
  );
};

export default MainComponent;

getQueryData를 통해서 캐시에 저장된 데이터를 수동으로 가져와 렌더링 한 걸 확인할 수 있다.

마치며

캐시 데이터를 클라이언트에서 어떻게 업데이트 할 수 있고 해당 캐시를 어떻게 가져오는지에 대해서 알아봤다.
주로 inValidateQueries를 유용하게 사용하는 사람들이 많던데 데이터가 많을시에는 서버에서 데이터를 다시 가져오다 보니 통신에도 부담이 생기고 렌더링 시 사용자의 경험측면에서도 단점이 있다는걸 느꼈다.

2개의 메서드를 섞어쓰거나 혹은 다른 유용한 메서드가 있을지는 모르겠지만 내가 할 프로젝트에서의 사용자 경험측면에서 보면 단점을 생각하더라도 둘 다 매우 유용한 메서드라고 생각한다.

profile
개발진행형

0개의 댓글