본문 바로가기
프론트엔드/NextJS

Server mutate시 react-query cache 사라짐 현상

by SeungYn 2023. 7. 15.

문제 발생

nextjs에서 sever mutate를 이용하려면 useRouter()를 사용하여 페이지를 refresh를 해줘야된다.

근데 나는 react-query와 같이 사용중이었는데 문제가 발생했다.

useRouter().refresh()를 하면 react-query의 캐시 데이터가 모두 사라졌다.

 

 

아래 사진을 잘 보면 button 클릭시 데이터들이 모두 지워짐

 

아래는 코드이다.

'use client';
import { useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/navigation';

async function fetchTest() {
  return fetch('/api/t', { method: 'get' }).then((res) => res.json());
}

export default function Test() {
  const router = useRouter();
  const { data } = useQuery(['test'], () => fetchTest());

  const onClick = async () => {
    router.refresh();
  };

  console.log('data', data, 123);
  return (
    <div>
      <button className='text-neutral-200 text-xl' onClick={onClick}>
        button
      </button>
      <p className='text-neutral-100 text-xl'>{JSON.stringify(data)}</p>
    </div>
  );
}

 

문제 해결

이 문제를 처음 발견했을때 하루를 날려버렸었다;;

원인은 QueryClient를 useState로 감싸주지 않았기 때문

 

아래 코드를 보면 useState로 QueryClient를 감싸주어서 해결했다.

'use client';
import {
  QueryClient,
  QueryClientConfig,
  QueryClientProvider,
} from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { ReactNode, useState } from 'react';

export default function ReactQueryContext({
  children,
}: {
  children: ReactNode;
}) {
  const options: QueryClientConfig = {
    defaultOptions: {
      queries: {
        staleTime: 4000,
        refetchOnMount: true,
      },
    },
  };

  const [client, setClient] = useState(new QueryClient(options));

  // if state is not used is not to work query-cache
  //const client = new QueryClient(options);
  return (
    <QueryClientProvider client={client}>
      {children}
      <ReactQueryDevtools />
    </QueryClientProvider>
  );
}

 

링크

아래는 해당 코드 테스트 깃허브 샘플파일 내가 만듬 👍

https://github.com/SeungYn/react-query-test

 

GitHub - SeungYn/react-query-test: react-query-test

react-query-test. Contribute to SeungYn/react-query-test development by creating an account on GitHub.

github.com

 

아래는 codesandbox에 만든 샘플인데 useState로 감싼것과 감싸지 않는 코드를 직접 몸으로 느낄수 있게 올려두었다.

 

잘 작동하는 버전

https://codesandbox.io/p/github/SeungYn/react-query-test/main?file=/src/context/ReactQueryContext.tsx:1,1&workspaceId=820da5ea-9550-4af7-97c2-97c230e411ba

 

CodeSandbox

CodeSandbox is an online editor tailored for web applications.

codesandbox.io

캐시 사라지는 버전

https://codesandbox.io/p/github/SeungYn/react-query-test/not-working-querycache?file=/src/context/ReactQueryContext.tsx:1,1&workspaceId=820da5ea-9550-4af7-97c2-97c230e411ba

 

CodeSandbox

CodeSandbox is an online editor tailored for web applications.

codesandbox.io

 

이유

그럼 이 문제에 대한 이유가 뭐였을까? 그리고 페이지를 refresh를 하는데 왜 캐시 데이터가 유지되는 걸까?

일단 리프레시를 해도 데이터가 유지되는 이유는 nextjs에 나와있었다 

 

한마디로 refresh를 해주면 클라이언트의 상태 데이터 손실 없이 서버에 요청을 하고 최신 데이터로 업데이트를 해주는 것이다.

https://nextjs.org/docs/app/api-reference/functions/use-router

 

Functions: useRouter | Next.js

Using App Router Features available in /app

nextjs.org

이러한 이유 때문에 QueryClient를 useState에 저장해 두면 refresh를 해도 캐시가 남아있는 것이다. 하지만 F5로 하면 지워짐

 

그리고 react-query 만든사람(?)의 블로그에서 QueryClient를 사용하려면 useState를 사용해서 안정적이게 사용하라고 글까지 써놨었다. 이유는 어떠한 이유로 앱이 re-render가 되면 캐시가 다날라간다고 한다.

https://tkdodo.eu/blog/react-query-fa-qs#2-the-queryclient-is-not-stable

 

이거 처음 당했을 때 킹받았었는데 지나고 보면 별게 아니네