3. RTK, RTK-query 사용기

mangojang·2023년 6월 3일
0

RTK 와 RTK-query 관련 일화는 더 많지만 뒤에 SSR 포스트와 더 연관 있어서, 일단 이번 포스트에서는 찾아봤었던 사용법 몇 가지와 발생했던 에러 해결에 대해 이야기 하겠다.

RTK-query setting

전체 코드는 여기를 확인하길 바란다.

header에 api key 적용하기

영화 데이터를 가져오기 위해서 header에 api key를 넣어서 보내야 했다.

RTK-query 를 이용하여 header의 값을 넣는 방법은 prepareHeaders 옵션을 이용하면 된다.

import { createApi, fetchBaseQuery, FetchBaseQueryError } from '@reduxjs/toolkit/query/react';

export const movieAPI = createApi({
	reducerPath: 'movieAPI',
	baseQuery: fetchBaseQuery({
		baseUrl: 'https://api.themoviedb.org/3',
		prepareHeaders: (headers, { getState }) => {
			//headers.set(key, value) 를 이용하여 header 값 설정
			headers.set('authorization', `Bearer ${process.env.NEXT_PUBLIC_API_KEY}`);
			return headers;
		},
	}),
	........
	}),
});

2개 이상의 API 통신을 이용한 값을 가져오고 싶을 때

메인 페이지 banner에 필요한 data를 가져오는 방식은 이러했다.

  1. 현재 상영작 목록을 api 통신으로 불러온다.
  2. 랜덤으로 하나를 선택하여 해당 영화 id에 따른 세부 정보를 api 통신으로 불러온다.

기존의 build.query의 query 옵션으로는 2개의 api를 한번에 다루지 못하였다. 그래서 찾아 본 결과, queryFn 옵션을 사용하면 async-await 을 사용 할 수 있고, 원하는 형태의 결과 값을 retrurn 받을 수 있다.

....
endpoints: build => ({
			getRandomMoviedetail: build.query({
				async queryFn(_arg, _queryApi, _extraOptions, fetchWithBQ) {
					const nowPlaying = (await fetchWithBQ(`${requests.fetchNowPlaying}?language=ko-KR`)) as NowPlaying;
					if (nowPlaying.error) return { error: nowPlaying.error as FetchBaseQueryError };
					const movieId = nowPlaying.data.results[Math.floor(Math.random() * nowPlaying.data.results.length)].id;
					const movieDetail = await fetchWithBQ(`/movie/${movieId}?append_to_response=videos&language=ko-KR`);
					return movieDetail.data ? { data: movieDetail.data } : { error: movieDetail.error as FetchBaseQueryError };
				},
				providesTags: ['NowPlaying'],
			}),
....
}),

non-serializable value 에러

로그인을 한 후 user 정보를 받아와서 userSlice에 넣는 과정에서 다음 과 같은 에러가 발생 했다.

Getting an error "A non-serializable value was detected in the state" when using redux toolkit - but NOT with normal redux

원인

Redux에서 값을 주고, 받을 때 object 형태의 값을 string 형태로 변환(JSON.stringify)하는데, 이 상황에서 변환이 불가능한 값을 전달했을 경우 나타나는 에러라고 한다.

아마 user 정보 object 안에 또 object 가 있는데 이것이 string으로 변환이 안되서 에러가 난 것 같다.

해결

redux store 설정 부분에서 middleware > getDefaultMiddleware > serializableCheck 옵션을 false로 설정한다.

const makeStore: MakeStore<any> = () =>
	configureStore({
		reducer: rootReducer,
		devTools: process.env.NODE_ENV == 'development' ? true : false,
		middleware: getDefaultMiddleware =>
			getDefaultMiddleware({
				serializableCheck: false,
			}).concat(logger, movieAPI.middleware),
	});

전체 코드는 여기를 확인 바란다.

참고 문헌

profile
한 걸음 한 걸음 계속 걷는 자가 일류다

0개의 댓글