tanstackQuery에서 useQuery, useMutation 타입 지정하기

React Query는 서버 상태 관리를 간단하고 효율적으로 할 수 있게 해주는 강력한 라이브러리이다

React Query는 제네릭 타입 형식으로 지원하고 있다

그래서 제네릭을 잘 사용한다면 타입을 보장 받으면서 편리하게 데이터를 다룰 수 있다 !

 

타입 지정을 안하면, 대부분 unknown, any 타입을 사용하고 있기 때문에 명시적으로 타입을 지정해서 비동기 상태의 타입 안정성을 확보하자

 

useQuery

useQuery 타입은 아래와 같다

export function useQuery<
  TQueryFnData = unknown, // queryFn의 리턴 값
  TError = unknown, // queryFn의 에러 형식
  TData = TQueryFnData, // data
  TQueryKey extends QueryKey = QueryKey
>

 

TQueryFnData , TError 

queryFn의 리턴값

const { data, error } = useQuery<number, AxiosError>(['todo'], getTodo);
// data = number | undefined
// error = AxiosError | null

 

TData : data에 담기는 실질적 타입

선택 옵션이므로, queryFn 데이터를 2차 가공하는 경우에만 사용되는 타입 지정해주면 3번째 타입, 지정 안하면 TQueryFnData

const { data } = useQuery<Todo[], AxiosError, number>({
    queryKey : ['todos'],
    queryFn: getTodos,
    select: todos => todos.length
});
// select로 todos의 length을 data에 담기로 했으니,
// 세 번째 제네릭 타입에 number를 필수적으로 넣어줘야 합니다.

 

TQueryKey

항상 string[] 형식으로 전달된다

type QueryKey = string | readonly unknown[];
// queryKey는 string 혹은 array 
// 하지만 query function에 전달 방식은 항상 array 형식으로 전달 => string[]

 

하지만, 명시적으로 배열에 어떤값이 들어가는지 지정해주고 싶을 때 사용한다

const { data } = useQuery<Todo, AxiosError, Todo, [string, number]>({
    queryKey: ['todos', id],
    queryFn : getTodo
});

 

 

useMutation

useMutation 타입은 아래와 같다

export function useMutaion<
  TData = unknown, // mutationFn
  TError = unknown, // mutationFn
  TVariables = void, // mutate
  TContext = unknown
>

 

TData, TError

mutatationFn의 실행 결과 타입이다

const { data } = useMutaion<TodoResponse>({
    mutationFn : postTodo, 
    onSuccess: res => {}
});
// data 타입은 TodoResponse | undefined
// onSuccess callback의 res 타입은 TodoResponse
const { error } = useMutation<TodoResponse, AxiosError>({
    mutationFn : postTodo, 
    onError: err => {} 
}
// error 타입은 AxiosError | null 
// onError callback의 err 타입은 AxiosError

 

TVariables

mutateFn의 인자 타입

const { mutate } = useMutation<TodoResponse, AxiosError, number>({
  mutationFn :postTodo, 
  onSuccess: (res, id) => {},
  onError: (err, id) => {},
  onMutate: id => {},
  onSettled: (res, err, id) => {},
});

return <button onClick={() => mutate(5)}>add</button>;

 

TContext

mutattionFn을 실행하기 전에 수행하는 onMutate의 return 타입

const { mutate } = useMutation<TodoResponse, AxiosError, number, number>({
  mutationFn : postTodo, 
  onSuccess: (res, id, nextId) => {},
  onError: (err, id, nextId) => {},
  onMutate: id => id + 1,
  onSettled: (res, err, id, nextId) => {},
});

// onMutate에서 return으로 주는 number
// onSuccess, onError의 세 번째 인자, onSettled의 네 번째 인자로 받아서 다룰 수 있습니다.

 

요약

참고자료

https://gusrb3164.github.io/web/2022/01/23/react-query-typescript/

https://despiteallthat.tistory.com/303