dotansimha / graphql-code-generator-community

MIT License
114 stars 144 forks source link

[typescript-react-query] add ability to customize react-query key with a directive #209

Open sciyoshi opened 2 years ago

sciyoshi commented 2 years ago

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

The react-query key is automatically generated from the query name, but there are situations where you might want to change the query key (e.g. for easier invalidation).

Describe the solution you'd like

Add a @reactQueryKey directive on QUERY to allow customizing the generated key.

Describe alternatives you've considered

Add an argument to the generated hook that allows specifying the key. This might be useful but also feels like it could be overkill.

EssamKayal96 commented 1 year ago

I don't know if my comment is related to this problem but I have a problem when using the generated hook by codgen and react-query plugins

I simply wrote a js file to match a pattern then change it to my needs

const fs = require('fs');

const filePath = 'src/generated/graphql.ts';
fs.readFile(filePath, 'utf8', (err, data) => {
  if (err) {
    console.error(err);
    return;
  }

  const pattern =
    /export const (\w+) = <TData = (\w+), TError = unknown>\(\s*(variables: \w+,\s*options\?: \w+<[^>]+>)\s*\)\s*=>\s*useQuery<([^>]+)>\(\s*\[([^\]]+)\]/gm;

  const modifiedContent = data.replace(
    pattern,
    (match, functionName, TData, variables, returnType, defaultQueryKey) => {
      const modifiedDeclaration = `export const ${functionName} = <TData = ${TData}, TError = Error>(${variables}, queryKey?: Array<unknown>) =>  useQuery<${returnType}>(queryKey ?? [${defaultQueryKey}]`;
      return modifiedDeclaration;
    }
  );

  fs.writeFile(filePath, modifiedContent, 'utf8', (err) => {
    if (err) {
      console.error(err);
      return;
    }
    console.log('File updated successfully!');
  });
});

before:

export const useGetAllCountriesQuery = <TData = GetAllCountriesQuery, TError = unknown>(
  variables: GetAllCountriesQueryVariables,
  options?: UseQueryOptions<GetAllCountriesQuery, TError, TData>
) =>
  useQuery<GetAllCountriesQuery, TError, TData>(
    ['GetAllCountries', variables],
    useAxios<GetAllCountriesQuery, GetAllCountriesQueryVariables>(GetAllCountriesDocument).bind(
      null,
      variables
    ),
    options
  );

after:

export const useGetAllCountriesQuery = <TData = GetAllCountriesQuery, TError = Error>(
  variables: GetAllCountriesQueryVariables,
  options?: UseQueryOptions<GetAllCountriesQuery, TError, TData>,
  queryKey?: Array<unknown>
) =>
  useQuery<GetAllCountriesQuery, TError, TData>(
    queryKey ?? ['GetAllCountries', variables],
    useAxios<GetAllCountriesQuery, GetAllCountriesQueryVariables>(GetAllCountriesDocument).bind(
      null,
      variables
    ),
    options
  );

hope this solves others problem

bzbetty commented 3 months ago

I was actually wondering if outputing the directives into the query/mutation metadata made sense, so you could do invalidation kind of like in this post https://tkdodo.eu/blog/automatic-query-invalidation-after-mutations

type Mutation {
  addLogin(args: LoginLogoutArgs!): [LogItem!]! @authorize(roles: ["CompanyEdit"]) @invalidates(keys: [Logins''])
}

would end up generating

useMutation([key], fn, {
 meta: {
 directives: { 
    authorize: { roles: ["CompanyEdit"] },
    invalidates: { keys: ["Logins"] }
 }
})

Then you could override the queryClient on settled or something to do the invalidation

but it'd also be flexible to allow other things too (eg checking roles before running mutation)