React Apollo useQuery hook with TypeScript
Asked Answered
P

3

8

I'm trying to get useQuery hook to work with TypeScript.

Here is my query

export const FETCH_LINKS = gql`
  query FetchLinks {
    feed {
      links {
        id
        createdAt
        url
        description
     }
  }
}
`;

I generated the types from GraphQL schema with graphql-codegen

export type Feed = {
  __typename?: 'Feed';
  links: Array<Link>;
  count: Scalars['Int'];
};

export type Link = {
  __typename?: 'Link';
  id: Scalars['ID'];
  createdAt: Scalars['DateTime'];
  description: Scalars['String'];
  url: Scalars['String'];
  postedBy?: Maybe<User>;
  votes: Array<Vote>;
};

In my component, I apply the type to useQuery hook

const { data, loading, error } = useQuery<Feed>(FETCH_LINKS);

The problem is that in the data variable I receive an object of the following shape:

{
feed: {
  __typename
  links
  count
  }
}

So, in order to loop through the array of links and render them on the page, I need to do data.feed.links.map() but the Feed type does not have a feed property on it and therefore, I get an error message Property 'feed' does not exist on type 'Feed' How do I rectify this inconsistency

Placebo answered 29/6, 2020 at 8:19 Comment(2)
The obvious solution is to edit the Feed type generated by graphql-codegen but it does not feel like a correct way to go about itPlacebo
try useQuery<{ feed: Feed }>Preter
P
6

You should utilize the typescript-operations plugin in addition to the typescript plugin. This way you will not only generate TS types for the GraphQL types in your schema, but you will also generate types based on the actual queries you use client-side. These additional types can then be plugged directly into the type variables used by the hooks.

Alternatively, you can also use the typescript-react-apollo plugin to generate your hooks for you.

If you don't want to use any additional plugins, you'll need to construct the appropriate types for your query and variables yourself:

interface FetchLinksData {
  feed: Feed
}
Pisci answered 29/6, 2020 at 8:28 Comment(0)
T
9

If you check documentation you will see that you would need to create one more interface to represent data:

interface FetchLinksData {
  feed: Feed[];
}

In component you could use that like this:

const { data, loading, error } = useQuery<FetchLinksData>(FETCH_LINKS);
const feeds = data.feed;
Thrashing answered 29/6, 2020 at 8:28 Comment(0)
P
6

You should utilize the typescript-operations plugin in addition to the typescript plugin. This way you will not only generate TS types for the GraphQL types in your schema, but you will also generate types based on the actual queries you use client-side. These additional types can then be plugged directly into the type variables used by the hooks.

Alternatively, you can also use the typescript-react-apollo plugin to generate your hooks for you.

If you don't want to use any additional plugins, you'll need to construct the appropriate types for your query and variables yourself:

interface FetchLinksData {
  feed: Feed
}
Pisci answered 29/6, 2020 at 8:28 Comment(0)
N
-2

Since you're using hooks provided by react-apollo, you should probably use the official apollo cli tool to generate types as well - https://github.com/apollographql/apollo-tooling#apollo-clientcodegen-output. Apollo codegen generates correct types out of the box without having to worry about adding additional plugins.

Nix answered 2/7, 2020 at 12:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.