ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • (삽질금지 시리즈) Nextjs getServerSideProps에서 SSR 할때 react-query 사용 hydrate fetchQuery와 prefetchQuery
    Next.js 2024. 2. 2. 13:23
    728x90

    개발 하면서 ssr를 이용하여 api를 요청 할때 try catch 구문을 이용하여 restapi의 error상태에 따라 error 페이지로 보내줄려고 했다.

    ssr에서 react-query를 사용 할때 hydrate 방법을 사용 했는데, 굉장히 흥미로운게 있었다.

     

    react-query를 ssr에서 사용 할때 

     const queryClient = new QueryClient();
    await queryClient.fetchQuery
    await queryClient.prefetchQuery

    이렇게 사용하는데

     

    - fetchQuery

     

    - perfetchQuery의 차이는

     

    fetchQuery : 리턴값이 있다. 

    prefetchQeury: 리턴값이 없다. 

    fetchQuery : Promise<TData>
    prefetchQeury: Promise<void>

     

    공식 문서의 예제에서는 prefetchQuery 메소드를 사용해서 데이터를 프리 패칭했다.
    prefetchQuery 메소드는 데이터를 프리 패칭하고 캐시할 뿐, 어떠한 결과 값을 리턴하지 않는다.
    반면에 fetchQuery 메소드는 데이터를 프리 패칭하고 캐시하고, 결과 값까지 리턴한다.

    따라서, 목적에 적합한 메소드를 선택해야 한다.

    단순히 프리 패칭만 하면 되는 경우 prefetchQuery 를 사용하면 되겠다.
    하지만, 서버 사이드 렌더링 시점에서 패치한 데이터의 값 자체를 사용해야 한다면 fetchQuery 를 사용한다.

     

    export const getServerSideProps = (async context => {
    	const queryClient = new QueryClient();
    	const { scheduleId } = context.params as { scheduleId: string };
        
        try {
        
        await queryClient.prefetchQuery<ScheduleItemResponse>(
    			['get-scheduleId', scheduleId],
    			async () => {
    				const { data } = await axiosAPI.get<ScheduleItemResponse>(
    					`/groups/75aca3da-1dac-48ef-84b8-cdf1be8fe37d/schedules/75aca3da-1dac-48ef-84b8-cdf1be8fe37d`,
    				);
    
    				return data;
    			},
    		);
    
    		return {
    			props: {
    				dehydratedState: dehydrate(queryClient),
    			},
    		};
    	} catch (e) {
    		console.log('eee=', e);
    		return {
    			notFound: true,
    		};
    	}
    }) satisfies GetServerSideProps;

     

    나는 당연히 console.log('eee=', e); 부분이 실행이 되고 notFound 페이지로 넘겨줄줄 알았다.

     

    social-frontend-1  | AxiosError: Request failed with status code 404
    social-frontend-1  |     at settle (file:///app/node_modules/axios/lib/core/settle.js:19:12)
    social-frontend-1  |     at IncomingMessage.handleStreamEnd (file:///app/node_modules/axios/lib/adapters/http.js:570:11)
    social-frontend-1  |     at IncomingMessage.emit (node:events:529:35)
    social-frontend-1  |     at endReadableNT (node:internal/streams/readable:1400:12)
    social-frontend-1  |     at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
    social-frontend-1  |   code: 'ERR_BAD_REQUEST',
    social-frontend-1  |   config: {
    social-frontend-1  |     transitional: {
    social-frontend-1  |       silentJSONParsing: true,
    social-frontend-1  |       forcedJSONParsing: true,
    social-frontend-1  |       clarifyTimeoutError: false
    social-frontend-1  |     },
    social-frontend-1  |     adapter: [ 'xhr', 'http' ],
    social-frontend-1  |     transformRequest: [ [Function: transformRequest] ],
    social-frontend-1  |     transformResponse: [ [Function: transformResponse] ],
    social-frontend-1  |     timeout: 0,
    social-frontend-1  |     xsrfCookieName: 'XSRF-TOKEN',
    social-frontend-1  |     xsrfHeaderName: 'X-XSRF-TOKEN',
    social-frontend-1  |     maxContentLength: -1,
    social-frontend-1  |     maxBodyLength: -1,
    social-frontend-1  |     env: { FormData: [Function], Blob: [class Blob] },
    social-frontend-1  |     validateStatus: [Function: validateStatus],

     

    갑자기 axios 에러가 떠버렸다.이게 뭔가 당연히 try 구문에서 에러가 발생했으니까 catch 구문으로 가야 되는거 아닌가?

     

    export const getServerSideProps = (async context => {
    	const queryClient = new QueryClient();
    	const { scheduleId } = context.params as { scheduleId: string };
        
        try {
        
        await queryClient.fetchQuery<ScheduleItemResponse>(
    			['get-scheduleId', scheduleId],
    			async () => {
    				const { data } = await axiosAPI.get<ScheduleItemResponse>(
    					`/groups/75aca3da-1dac-48ef-84b8-cdf1be8fe37d/schedules/75aca3da-1dac-48ef-84b8-cdf1be8fe37d`,
    				);
    
    				return data;
    			},
    		);
    
    		return {
    			props: {
    				dehydratedState: dehydrate(queryClient),
    			},
    		};
    	} catch (e) {
    		console.log('eee=', e);
    		return {
    			notFound: true,
    		};
    	}
    }) satisfies GetServerSideProps;

     

    웃긴건 fetchQuery 즉, 리턴값이 있으면 아주 정상적으로 catch 구문이 실행 되고 notFound 페이지로 보내준다.

     

    문득 드는 생각은 아 내가 axios 에러처리를 무엇인가 잘못 했을 수 도 있겠다 싶었다.

     

     

    728x90
Designed by Tistory.