그럼에도 불구하고

👨‍💻

[React Query] React Query를 TypeScript로 사용할 때 Type 지정 본문

React/React query

[React Query] React Query를 TypeScript로 사용할 때 Type 지정

zenghyun 2023. 10. 14. 14:29

 

React Query를 TS에서 사용할 때 Type은 어떻게 지정해야 할지 알아보겠습니다.

 

Start!

 

🧑🏻‍💻 React Query TypeScript 

React Query는 TypeScript의 제네릭(Generics)을 많이 사용합니다. 이는 라이브러리가 실제로 데이터를 가져오지 않고 API가 반환하는 데이터 유형을 알 수 없기 때문입니다. 

공식 문서에서는 타입스크립트를 그다지 광범위하게 다루지 않고, useQuery를 호출할 때 기대하는 제네릭을 명시적으로 지정할 수 있게 알려줍니다. 

 

📌 useQuery

현재 useQuery가 갖고 있는 제네릭은 4개이며, 다음과 같습니다.

  1. TQueryFnData: useQuery로 실행하는 query function의 실행 결과의 타입을 지정하는 제네릭 타입입니다.
  2. TError: query function의 error 형식을 정하는 제네릭 타입입니다. 
  3. TData: useQuery의 data에 담기는 실질적인 데이터의 타입을 말합니다. 첫 번째 제네릭과의 차이점은 select와 같이 query function의 반환 데이터를 추가 핸들링을 통해 반환하는 경우에 대응할 수 있는 타입이라고 생각하면 좋습니다.
  4. TQueryKey: useQuery의 첫 번째 인자 queryKey의 타입을 명시적으로 지정해 주는 제네릭 타입입니다.
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
// useQuery의 타입
export function useQuery<
TQueryFnData = unknown, 
TError = unknown,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey
>
 
// useQuery 타입 적용 예시 
const { data } = useQuery<
SuperHeros,
AxiosError,
SuperHeroName[],
[string, number]
>({
    queryKey: ["super-heros", id], 
    queryFn: getSuperHero,
    select: (data) => {
        const superHeroNames = data.data.map((hero) => hero.name);
        return superHeroNames;
    },
});
 
/**
 주요 타입
 * data: `SuperHeroName[]`
 * error: `AxiosError<any, any>`
 * select: `(data: SuperHeros): SuperHeroName[]`
 */
cs

 

📌 useMutation

useMutation도 useQuery와 동일하게 현재 4개이며, 다음과 같습니다.

  1. TData: useMutation에 넘겨준 mutation function의 실행 결과의 타입을 지정하는 제네릭 타입입니다.
  2. TError: useMutation에 넘겨준 mutation function의 error 형식을 정하는 제네릭 타입입니다
  3. TVariables: mutate 함수에 전달할 인자를 지정하는 제네릭 타입입니다.
    1. onSuccess(2번째 인자), onError(2번째 인자), onMutation(1번째 인자), onSettled(3번째 인자) 인자의 타입으로 활용됩니다.
  4. TContext: mutation function을 실행하기 전에 수행하는 onMutate 함수의 return값을 지정하는 제네릭 타입입니다.
    1. onMutate의 결과 값의 타입을 onSuccess(3번째 인자), onError(3번째 인자), onSettled(4번째 인자)에서 활용하려면 해당 타입을 지정해야 합니다.
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
// useMutation의 타입
export function useMutation<
    TData = unknown,
    TError = unknown,
    TVariables = void,
    TContext = unknown
> 
 
// useMutation의 타입 적용 예시 
const { mutate } = useMutation<Todo, AxiosError, number, number>(postTodo, {
    onSuccess: (res, id, nextId) => {},
    onError: (err, id, nextId) => {},
    onMutate: (id) => id + 1;
    onSettled: (res, err, id, nextId) => {}, 
}); 
 
const onClick = () => {
    mutate(5);
}; 
 
/*
    주요 타입
    data: 'Todo',
    error: 'AxiosError<any, any>'
    onSuccess: '(res: Todo, id: number, nextId: number)'
    onError: '(err: AxiosError, id: number, nextId: number)' 
    onMutate: '(id: number)'
    onSettled: '(res: Todo, err: AxiosError, id: number, nextId: number)',
*/
cs

 

📌 useInfiniteQuery

현재 useInfiniteQuery가 갖고 있는 제네릭은 4개이며, useQuery와 유사합니다.

  1. TQueryFnData: useInfiniteQuery로 실행하는 query function의 실행 결과의 타입을 지정하는 제네릭 타입입니다.
  2. TError: query function의 error 형식을 정하는 제네릭 타입입니다.
  3. TData: useInfiniteQuery의 data에 담기는 실질적인 데이터의 타입을 말합니다. 첫 번째 제네릭과의 차이점은 select와 같이 query function의 반환 데이터를 추가 핸들링을 통해 반환하는 경우에 대응할 수 있는 타입이라고 생각하면 좋습니다.
  4. TQueryKey: useInfiniteQuery의 첫 번째 인자 queryKey의 타입을 명시적으로 지정해 주는 제네릭 타입입니다. 
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
32
33
34
35
// useInfiniteQuery의 타입
export function useInfiniteQuery<
    TQueryFnData = unknown,
    TError = unknown,
    TData = TQueryFnData,
    TQueryKey extends QueryKey = QueryKey 
>
 
// useInfiniteQuery 활용 
const fetchColors = async ({ pageParam }) => {
    const { page = 1, etc } = pageParam; 
 
    return await axios.get(`http://localhost:4000/colors?_limit=2&_page=${page}`);
};
 
const { mutate } = useInfiniteQuery<Colors, AxiosError, Colors, ["colors"]>(
    ["colors"],
    ({ pageParam = 0 }) => {
        fetchColors({ page: pageParam });
    },
    {
        getNextPageParam: (lastPage) => {
            return allPages.length < 4 && allPages.length + 1
        },
        ...options,
    }
);
 
/*
     주요 타입
    data: InfiniteData<ModeListResponse>
    error: AxiosError<any, any>
    select: InfiniteData<ModeListResponse>
    getNextPageParam: GetNextPageParamFunction<Colors> 
*/
cs

 

🏷️ REF

https://tanstack.com/query/v4/docs/react/typescript

https://www.youtube.com/watch?v=VtWkSCZX0Ec&list=PLC3y8-rFHvwjTELCrPrcZlo6blLBUspd2&index=3 

 

Comments