GraphQL과 React Query로 서버 상태 관리하기
GraphQL
React Query
Hook
2024년 2월 2일
실무에서 React Query와 GraphQL을 같이 사용해야 했는데, 구글링 해보니 자료가 많이 없어서 제가 사용한 방법을 정리해보려고 합니다.
@apollo/client
의 useQuery
와 useMutation
의 인터페이스를 참고하였습니다.
useQuery #
import { RequestOptions, Variables, request } from 'graphql-request'
import {
DefaultError,
UndefinedInitialDataOptions,
useQuery as useTanstackQuery,
} from '@tanstack/react-query'
export const useQuery = <
T,
V extends Variables = Variables,
TError = DefaultError,
>({
document,
variables,
...rest
}: Pick<RequestOptions<V>, 'document' | 'variables'> &
Omit<
UndefinedInitialDataOptions<
T,
TError,
T,
[
RequestOptions<V>['document'],
RequestOptions<V>['variables'] | undefined,
]
>,
'queryKey' | 'queryFn'
>) => {
// queryKey는
const queryKey: [
RequestOptions<V>['document'],
RequestOptions<V>['variables'] | undefined,
] = [document, variables]
return useTanstackQuery({
queryKey,
queryFn: ({ queryKey }) =>
// queryKey[0], queryKey[1]은 항상 document, variables인 것이 보장됨
request<T>('https://example.com/graphql', queryKey[0], queryKey[1]),
...rest,
})
}
document
와 variables
가 동일하다면 같은 쿼리라고 보고 queryKey
를 구성하였습니다.
아래 코드를 보시면 @apollo/client
의 useQuery
를 사용할 떄와 비슷하게 사용할 수 있다는 것을 확인 할 수 있습니다.
// @apollo/client의 경우
const { loading, error, data } = useQuery<
GetDogPhotoQuery,
GetDogPhotoQueryVariables
>(GET_DOG_PHOTO, {
variables: { breed },
skip: true,
})
// 작성한 훅의 경우
const { isLoading, error, data } = useQuery<
GetDogPhotoQuery,
GetDogPhotoQueryVariables
>({
document: GET_DOG_PHOTO,
variables: { breed },
enabled: false,
})
useMutation #
import {
DefaultError,
UseMutationOptions,
useMutation as useTanstackMutation,
} from '@tanstack/react-query'
import request, { RequestOptions, Variables } from 'graphql-request'
export const useMutation = <
T,
V extends Variables = Variables,
TError = DefaultError,
>({
document,
...rest
}: Pick<RequestOptions<V>, 'document'> &
Omit<UseMutationOptions<T, TError, V>, 'mutationKey' | 'mutationFn'>) => {
const mutationKey: [RequestOptions<V>['document']] = [document]
return useTanstackMutation({
mutationKey,
mutationFn: (variables) =>
request<T>(
'https://example.com/graphql',
document,
variables,
),
...rest,
})
}
이렇게 하면 @apollo/client
의 useMutation
훅 인터페이스와 비슷하게 사용할 수 있습니다.
// @apollo/client의 경우
const [addTodo, { data, loading, error }] = useMutation<
AddTodoMutation,
AddTodoMutationVariables
>(ADD_TODO)
addTodo({ variables: { type: input.value } })
// 작성한 훅의 경우
const {
mutate: addTodo,
isLoading,
error,
data,
} = useMutation<AddTodoMutation, AddTodoMutationVariables>({
document: ADD_TODO,
})
addTodo({ type: input.value })