[Next.js] SSR + react-query Hydration에서의 serializing 에러

hzn·2023년 4월 15일
0

PROJECT🏝

목록 보기
17/24
post-thumbnail
post-custom-banner

☄️ 문제 상황

  • 상세 페이지에서 getServerSideProps를 사용해 서버에서 클라이언트로 데이터를 props로 넘겨주려고 하는데 serializing 에러가 발생했다.

Server Error
Error: Error serializing .dehydratedState.queries[0].state.data.headers returned from getServerSideProps in "/nearby/[id]".
Reason: object ("[object AxiosHeaders]") cannot be serialized as JSON. Please only return JSON serializable data types.

🚑 에러 발생 코드

pages/nearby/[id].tsx

export async function getServerSideProps(context: any) {
  const queryClient = new QueryClient();
  const { id } = context.params;
  await queryClient.prefetchQuery(['productDetail'], () =>
    getProductDetail(id)
  );

  return {
    props: {
      id,
      dehydratedState: dehydrate(queryClient),
    },
  };
}
...
export default function ProductDetail({ id }: productDetailType) {
  const { data } = useQuery(['productDetail'], () => getProductDetail(id));

api/detail.ts (productDetail 데이터 요청 함수)

export function getProductDetail(id: string) {
  return axios.get(`${REQUEST_URL}/api/boards/${id}`, {
    headers: {
      Authorization: Cookies.get('access_token'),
      Refresh: Cookies.get('refresh_token'),
    },
  });
}

🧐 원인

  • getServerSideProps를 사용해 서버에서 클라이언트로 데이터를 props로 넘겨줄 때, props로 전달되는 값(dehydrate(queryClient))에 JSON으로 변환이 불가능한 것들(ex. 함수 등)이 포함되어 있을 경우 해당 에러가 발생한다.

  • props로 넘겨주는 것은 AxiosResponse 타입(Promise 객체)이 아니라 여기서 data를 추출한 형태여야 한다.

✅ 해결 방법

  • 데이터를 요청하는 함수(getProductDetail)가 data를 추출해서 리턴하도록 수정
  • 데이터 요청 함수(getProductDetail)는 원래 Promise 객체(AxiosResponse 타입)를 리턴하는 형태로 작성되었으나, 이를 Promise 객체에서 data를 추출해 리턴하는 것으로 수정했다.
  • axios의 처리를 기다려야 하므로 async-await 처리 해준다.

api/detail.ts (productDetail 데이터 요청 함수)

export async function getProductDetail(id: string) {
  const res = await axios.get(`${REQUEST_URL}/api/boards/${id}`, { // axios가 처리될 때까지 기다려야 하므로 async-await 처리
    headers: {
      Authorization: Cookies.get('access_token'),
      Refresh: Cookies.get('refresh_token'),
    },
  });

  return res.data; // res에서 data를 추출해서 리턴
}

레퍼런스

                                                   
post-custom-banner

0개의 댓글