최근에 했던 프로젝트에 리액트 쿼리를 활용하려고 했으나 흐지부지 쓰지 못했던게 아쉬워서 다음 프로젝트에서는 제대로 사용하려고 공부하기 위한 리액트 쿼리 정리이다.
mutation으로 데이터를 업데이트 했을 때 캐시에 있는 데이터는 어떻게 업데이트할 수 있을까?
대표적으로 2가지 방법이 있다.
invalidateQuries
setQueryData
이번 섹션에서는 위 2가지 메서드에 대해서 알아보자
inValidateQuery
는 현재 캐싱된 데이터를 무효화시키고 새로운 데이터를 가져오게 하는 메서드이다.
즉, post요청을 통해서 서버의 데이터를 업데이트 했을 경우 기존에 있던 캐시 데이터를 무효화시켜서 서버에서 새로운 데이터를 받아와 서버와 클라이언트의 데이터를 동일하게 만들고 최신으로 유지시킬 수 있는 것이다.
하지만 해당 메서드는 서버에서 다시 데이터를 받아오는 작업을 하므로 데이터가 많아진다면 사용자 경험 측면에서 데이터를 버리고 서버에서 다시 받아오는 과정이 답답하게 느껴질 수 있다는 단점이 있다.
await queryClient.invalidateQueries({
queryKey: ['posts'],
exact,
refetchType: 'active',
}, { throwOnError, cancelRefetch })
queryKey
무효화 시킬 키
refetchType
해당 데이터가 어떤 상태인지에 따라서 서버에서 데이터를 다시 받아오는지를 결정할 수 있다.
active
active
상태일 때 useQuery
백그라운드에서 해당 데이터를 다시 가져온다.inactive
inactive
상태일 때 useQuery
백그라운드에서 해당 데이터를 다시 가져온다.all
useQuery
백그라운드에서 해당 데이터를 다시 가져온다.none
options
throwOnError
cancelRefetch
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"을 정의하면 해당 키가 어떤 상태인지 상관없이 무조건 데이터를 서버에서 다시 받아오게 된다.
setQueryData
는 캐시 데이터를 수동으로 설정하는 메서드이다.
서버에서 데이터를 다시 가져오는 inValidateQuries
와는 달리 쿼리 데이터를 클라이언트에서 바꿔주는 메서드이다.
서버와 클라이언트의 데이터가 실시간으로 동기화되고 있지는 않지만 네트워크 요청을 기다릴 피룡가 없어서 사용자 경험에서는 데이터를 업데이트 할 시 자연스러운 데이터 변환을 경험할 수 있다.
queryClient.setQueryData(queryKey, updater)
queryKey
updater
updater
에 정의할 수 있다.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값을 넣으면 해당 값은 캐시에 저장이 되지 않는걸 확인할 수 있다.
getQueryData
캐시에 저장된 데이터를 가져오는 메서드이다.
사실 해당 메서드는 생각 안하고 있었는데 캐시를 정의한걸 어떻게 가져올수 있을까? 를 생각해보다가 찾은 메서드라 정리해본다.
const data = queryClient.getQueryData(queryKey)
queryKey
에 해당하는 데이터가 없다면 undefined를 반환한다.
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개의 메서드를 섞어쓰거나 혹은 다른 유용한 메서드가 있을지는 모르겠지만 내가 할 프로젝트에서의 사용자 경험측면에서 보면 단점을 생각하더라도 둘 다 매우 유용한 메서드라고 생각한다.