1seul357

Query Keys Factory 본문

TIL

Query Keys Factory

1seul 2024. 10. 18. 16:17

 

Query Keys

React Query는 queryKey에 따라 캐싱을 관리한다. queryKey는 문자열, 배열 등으로 구성될 수 있는데, 이때 주의할 점은 queryKey는 중복되지 않게 작성되어야 한다는 것이다.

 

문자열 queryKey

문자열 queryKey가 전달되면 내부적으로 배열로 변환된다.

const { data } = useQuery({
    queryKey: 'todos',    // queryKey === [’todos’]
    queryFn: () => getTodoList()
})

 

배열 queryKey

queryKey는 배열의 형태로 작성될 수 있다. 또한 query 함수가 변수에 의존할 수도 있는데, 이때는 queryKey에 변수를 포함하면 된다.

const { data } = useQuery({
    queryKey: ['todo', 5],    // queryKey === ['todo', 5]
    queryFn: () => getTodoList()
})

 

아래 코드의 queryKey는 todoId에 의존한다.

const { data } = useQuery({
    queryKey: ['todos', todoId], 
    queryFn: () => fetchTodoById(todoId)
});

 

Query Key Factory

위 코드처럼 queryKey를 데이터를 가져올 때 마다 작성해도 된다. 하지만 queryKey를 한번에 보기 힘들다는 단점이 있고, 비슷한 API 함수 호출에 대한 queryKey를 관리하기 어렵다는 단점이 있다. API가 변경되거나 더 나은 유지보수를 위해서 비슷한 기능, 연관성이 있는 함수들에 대한 queryKey를 구조화해서 관리하는 것이 좋다.

import { queryOptions } from '@tanstack/react-query';
import { getBadges, getCalendarDate, getMyInformation, getProfileItems, getRecord } from './api';
import { TElementId } from '@shared/model/types';

export const myPageQueryies = {
    myPage: () => ['myPage'],
    learnerInfo: () => [...myPageQueryies.myPage(), 'learnerInfo'],
    /** 마이페이지 기본 정보 조회 */
    getLearnerInfo: (date: string) =>
        queryOptions({
            queryKey: [...myPageQueryies.learnerInfo(), date],
            queryFn: () => getMyInformation(date)
        }),
    /** 월별 캘린더 조회 */
    getCalendarData: (date: string) =>
        queryOptions({
            queryKey: [...myPageQueryies.myPage(), 'calendarDate', date],
            queryFn: () => getCalendarDate(date)
        }),
    /** 최고기록 조회 */
    getRecordList: (option: string) =>
        queryOptions({
            queryKey: [...myPageQueryies.myPage(), 'record', option],
            queryFn: () => getRecord(option)
        }),
    /** 배지 조회 */
    getBadges: () =>
        queryOptions({
            queryKey: [...myPageQueryies.myPage(), 'badges'],
            queryFn: () => getBadges()
        }),
    /** 프로필 아이템 리스트 조회 */
    getProfilItems: () =>
        queryOptions({
            queryKey: [...myPageQueryies.myPage(), 'profileItems'],
            queryFn: () => getProfileItems()
        })
};

마이페이지와 관련이 있는 모든 queryKey를 myPageQueryies 변수에 정의하였다. queryKey 배열은 각각 페이지명, 기능 이름에 대해서 작성했고, api 호출 함수에 의존값이 있다면 세번째 값부터 작성하였다. queryKey와 query 함수를 함께 작성할 수 있기 때문에 컴포넌트에서는 API 호출 함수를 import 하지 않아도 된다.

 

 

 

👇🏻 myPageQueryies를 사용하는 방법은 다음과 같다.

const calendarDate = filteredDate(date);
return useQuery({ 
    ...myPageQueryies.getCalendarData(calendarDate), 
    refetchOnMount: false 
});

useQuery를 사용하여 데이터를 호출할 때, 호출 함수는 가져오지 않고 myPageQueryies만을 통해 API를 호출할 수 있다.

 

 

 

쿼리를 무효화할 때도 유용하게 사용할 수 있다.

queryClient.invalidateQueries({ 
    queryKey: myPageQueryies.myPage()
});

myPageQueryies.myPage()로 정의된 queryKey가 포함된 모든 쿼리가 무효화된다. myPageQueries에서 작성된 queryKey는 모두 myPageQueryies.myPage()가 포함되어 있기 때문에 모든 쿼리가 무효화된다.

💡 쿼리를 무효화하면 새로운 데이터를 가져와서 캐싱 값을 refetch 한다.

'TIL' 카테고리의 다른 글

Semantic Tag  (0) 2024.10.29
dependencies와 devDependencies  (1) 2024.10.22
startTransition  (4) 2024.10.16
쿼리 스트링과 searchParams  (1) 2024.10.07
react-player  (0) 2024.08.18