graphql-code-generator-community icon indicating copy to clipboard operation
graphql-code-generator-community copied to clipboard

typescript-react-query uses deprecated (v3.x) `useQuery` arguments

Open AlanSl opened this issue 2 years ago • 3 comments
trafficstars

Is your feature request related to a problem? Please describe.

typescript-react-query generates query hooks that call useQuery using the old v3.x syntax of useQuery(queryKey, queryFn, options), which is deprecated and support will be removed in v5.

While this syntax still works in @tanstack/react-query v4.x, the official v4.x syntax (and v5.x beta) is to just pass one object, useQuery(options), which can contain queryKey and queryFn as properties.

The main practical impact of this are:

  • v5.x (currently in beta) will remove support for this syntax, so generated hooks will not be compatible with v5
  • It causes a limitation where it is not currently possible to pass a custom fetcher function to a generated hook. Calling useSomeGeneratedQuery(variables, { queryFn: somefn }) doesn't work as expected. someFn is never used (presumably because in the old v.3.x syntax, queryFn wasn't a supported option, it was passed as the second argument which is hardcoded in generated hooks).

Describe the solution you'd like

An option to generate useQuery hooks that use the >=4.x syntax. They'd probably look like this:

export const useSomeDataQuery = <TData = SomeDataQuery, TError = unknown>(
  variables?: SomeDataVariables,
  options?: UseQueryOptions<SomeDataQuery, TError, TData>
) =>
  useQuery<UseQueryOptions<SomeDataQuery, TError, TData>>({
    queryKey: variables === undefined ? ['SomeData'] : ['SomeData', variables],
    queryFn: fetchData<SomeDataQuery, SomeDataQueryVariables>(SomeDataDocument, variables)
    ...options // spread last so, unlike in the current implementation, options.queryFn will be applied and used
  })

That should be compatible with v5.x, match the docs for v4.x, and enable usage like this (which isn't currently possible):

const { data, isLoading, ...etc } = useSomeDataQuery(variables, {
  // with the current syntax, this is supposedly a valid option but doesn't do anything
  queryFn: someDifferentFnForThisCase
})

Describe alternatives you've considered

This could also be the default behaviour since it's the documented syntax for v4.x but that might be a breaking change so it's probably best to make it an opt-in option, then become the default in this package's v5.x release?

AlanSl avatar Sep 07 '23 10:09 AlanSl

As a temporary work around for the lack of queryFn option support, I'm doing something like this:

In codegen.ts config:

export default {
  // ...
  generates: {
    // ...
    config: {
      // ...
      exposeFetcher: true,
      exposeQueryKeys: true
    }
  }
}

In the hook that uses the query:

import { useSomeDataQuery, type SomeDataQuery } from './useGeneratedGraphqlHooks'
import { useQuery } from '@tanstack/react-query'

const transformSomeData = (data: SomeDataQuery) => {
  // custom query function logic here
}
const queryKey = useSomeDataQuery.getKey() // generated if `exposeQueryKeys: true`  in config
const fetcher = useSomeDataQuery.fetcher() // generated if `exposeFetcher: true`  in config
const queryFn = () => fetcher().then(transformSomeData)

const useSomeData = () => {
  // This will benefit from typescript signatures etc based on `SomeData` codegen content
  const { data, isLoading, ...etc } = useQuery({ queryKey, queryFn, ...moreOptions })
  // ...

AlanSl avatar Sep 08 '23 16:09 AlanSl

Although it doesn't allow a fetcher option override with v4, this PR adds support for react-query v5 with the updated object format

rliljest avatar Oct 23 '23 13:10 rliljest

codegen.ts now supports:

config: {
   reactQueryVersion: 5
}

ceefour avatar Dec 19 '23 13:12 ceefour