일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- React 18 Nextjs
- react-helmet
- React18
- Programmers
- background: url
- Babel
- React API 참고서
- Nextjs React 18
- next13 head
- background tab
- notFound()
- React 18
- background setttimeout
- Render Props
- Nextjs
- background setInterval
- React 고급안내서
- RTK Query
- CSS
- Javascript
- 고급안내서
- getUTCDate
- react hook
- React 공식문서
- React 고급 안내서
- react
- Next13
- hook
- codingtest
- context
Archives
- Today
- Total
akjfal
RTK 기본 개념 정리 본문
RTK Query를 왜 나왔냐?
💡 결론 : 데이터 fetching과 caching 로직을 줄이기 위해서!
데이터를 가져오는데는 해줘야 할 일이 많습니다.
- 가져오는동안 로딩창
- 중복데이터 호출도 고려
- 최적화
- 캐쉬도 관리
기존엔 상태 관리와 엮어서 해결하려던 부분을 별도의 작업이라고 생각하기 시작했습니다.
RTK Query는 createSlice랑 craeteAsyncThunk로 만들어진 리덕스 라이브러리입니다.. 그리고 Query를 통해서 데이터 로딩 등 컴포넌트를 만들고 화면을 구성하는데 필요한 값들을 제공해줍니다.
초기 세팅
App.tsx
// 기존 Redux가 있으면 사용하면 안됩니다!
function App(props) {
...
return (
//
<<ApiProvider api={api}>
{children}
</Provider>
)
}
API.ts
export const api = createApi({
// 쿼리에 대한 동작 선언
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
// 요청이 보내질 장소
endpoints: (builder) => ({
// 선언해두면 발동
getApi: builder.query({
query: () => '/'
}),
// 함수를 호출 시킬 시 발동!
setApi: builder.mutation({
// 요청을 보낼 URL
query: ({id, ...patch}) => ({
url: `/set/${id}`,
// Get, Patch, Delete 모두 가능
method: 'Post' ,
body: patch
})
});
// API 호출을 위해 사용!
export const { useGetApiQuery } = api;
// store 세팅을 위해 사용!
export const { reducerPath, reducer, middleware } = api
RootStore.ts
import { reducerPath, reducer, middleware } from './api.ts';
import { middleware2 } from './api2.ts';
export const store = configureStore({
reducer: {
// 한개만!!
[reducerPath]: reducer
},
// 사용하는 커스텀, 라이브러리 미들웨어 전부
middleware: gDM => gDM().concat(middleware, middleware2)
});
// refetch 관련 동작을 사용할 때 선택적으로 사용해요.
setupListeners(store.dispatch);
API 사용하기
사용하는 컴포넌트or페이지.tsx
import { api, useGetApiQuery, usePostApiMutation } = from './api';
export default function App(){
const { data, isLoading, isFetching, error } = useGetApiQuery();
// 똑같이 사용가능한 방식이에요
const { data, isLoading, isFetching, error } = api.endpoints.getApi.useQuery();
const [mutationApi, mutationData] = usePostApiMutation();
// 똑같이 사용가능한 방식이에요
const [mutationApi, mutationData] = api.endpoints.getApi.usePostApiMutation(id);
...
const handleClick = async () => {
await mutationApi(body);
}
기능
다양한 부분을 지정, 커스텀 가능
const axiosBaseQuery =
(
{ baseUrl }: { baseUrl: string } = { baseUrl: '' }
): BaseQueryFn<
{
url: string
method: AxiosRequestConfig['method']
data?: AxiosRequestConfig['data']
params?: AxiosRequestConfig['params']
},
unknown,
unknown
> =>
async ({ url, method, data, params }) => {
try {
const result = await axios({ url: baseUrl + url, method, data, params })
return { data: result.data }
} catch (axiosError) {
let err = axiosError as AxiosError
return {
error: {
status: err.response?.status,
data: err.response?.data || err.message,
},
}
}
}
export const rootApi = createApi({
// baseQuery: fetchBaseQuery({ baseUrl: '/' }),
baseQuery: axiosBaseQuery({ baseUrl: '/' }),
endpoints: () => ({}),
});
// injectionEndpoints
// 오버라이딩 할지 말지 overrideExisting 옵션을 통해 설정 가능
export const customApi= rootApi.injectEndpoints({
tagTypes: ['login'],
endpoints: (build) => ({
getApi: build.query({
query: (id) => `/${id}`,
// API 성공했을 때
transformResponse
// 실패 했을 때
transformErrorResponse
// key
providesTags
// 캐시값을 조절 가능
onCacheEntryAdded
// 캐시 유지시간
keepUnusedDataFor
}),
setApi: build.mutation({
// queryFn : query를 좀 더 자세히 쓸 때
query: ({id, ...patch}) => ({
url: `/set/${id}`,
method: 'Post' ,
body: patch
})
transformResponse
transformErrorResponse
// 무효화 시킬 key
invalidatesTags
// 캐시 업데이트 방식 지정
updateQueryData
}),
}),
});
// Auto-generated hooks
export const { useGetApiQuery, useSetApiMutation } = keepLoginApi;
// useQuery : 데이터 가져오기
// useQuerySubscription : refetch용이면서 자동 트리거
// useQueryState : 캐쉬된 데이터 읽기
// useLazyQuery : 데이터를 가져오는 시점을 수동으로
// useLazyQuerySubscription : refetch 수동으로 제어 및 캐시 존재시 스킵
// Possible exports
export const { endpoints, reducerPath, reducer, middleware } = keepLoginApi;
// query
const { data, currentData, error, isUninitialized, isLoading, isFetching, isSuccess, isError}
=useQuery(skip, pollingInterval, selectFromResult, refetchOnMountOrArgChange, refetchOnFocus, refetchOnReconnect)
// mutation
const { data, error, isUninitialized, isLoading, isSuccess, isError, reset }
= useMutation(selectFromResult, fixedCacheKey)
Optimistic Update and Pessimistic Update
pessimistic update → 캐쉬 된 데이터를 업데이트하기 전 서버의 응답을 기다림
optimistic update → 일단 업데이트함
💡 modest-hugle-sl98x3 - CodeSandbox
!https://codesandbox.io/csb-ios.svg
updateQueryData RTKquery로 클라이언트에서만 쿼리 데이터를 조작하고 싶다면
유틸
prefetch
데이터 미리 가져오기
dispatch(api.util.prefetch('getPosts', undefined, { force: true }))
updateQueryData
데이터를 업데이트해줌
const patchCollection = dispatch(
api.util.updateQueryData('getPosts', undefined, (draftPosts) => {
draftPosts.push({ id: 1, name: 'Teddy' })
})
)
upsertQueryData
캐시에 업서트하기위한 인공 APi 요청 작업 생성자
await dispatch(
api.util.upsertQueryData('getPost', { id: 1 }, { id: 1, text: 'Hello!' })
)
Comments