Querying for Users

Learn to enable querying for union types in a React application.

A new page

In order to query for users, let’s create a brand new page within our application. We will create a new file at pages/users/[username].tsx for this. This page will be matched by an address such as http://*address_to_app*/users/radar12. Here is the code that we will put on this page:

import { useRouter } from "next/router";
import { ApolloProvider } from "@apollo/client";
import client from "client";
import UserProfile from "components/Users/UserProfile";
function User(){
const router = useRouter();
const { username } = router.query;
return (
<ApolloProvider client={client}>
<UserProfile username={username as string} />
</ApolloProvider>
);
}
export default User;
Our new pages/users/[username].tsx file

This page uses the useRouter hook from next/router to load the username from the route. The component then wraps another component called UserProfile in the same ApolloProvider and Layout component that we used in our pages/index.tsx file. The ApolloProvider component allows us to run GraphQL queries within the UserProfile component.

Let’s go ahead and create that new file for a component now. Rather than starting with a component this time, we’ll start with the GraphQL query and then use what that returns to inform the shape of our component. Let’s add the GraphQL query to a new file.

import gql from "graphql-tag";
const userQuery = gql`
query user($username: String!) {
result: user(username: $username) {
... on SuspendedUser {
id
username
suspensionReason
}
... on User {
id
username
}
}
}
`;
Our new file for the User component

Running GraphQL Code Generator with only the query present in our component's file generates the following src/generated/graphql.tsx file.

Press + to interact
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
export type Maybe<T> = T | null;
export type InputMaybe<T> = Maybe<T>;
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
const defaultOptions = {}
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
ID: string;
String: string;
Boolean: boolean;
Int: number;
Float: number;
/** The `Upload` scalar type represents a file upload. */
Upload: any;
};
export type Book = {
__typename?: 'Book';
id: Scalars['ID'];
title: Scalars['String'];
};
export enum CacheControlScope {
Private = 'PRIVATE',
Public = 'PUBLIC'
}
export type Mutation = {
__typename?: 'Mutation';
createBook: Book;
updateBookTitle: Book;
};
export type MutationCreateBookArgs = {
title: Scalars['String'];
};
export type MutationUpdateBookTitleArgs = {
id: Scalars['ID'];
title: Scalars['String'];
};
export type Query = {
__typename?: 'Query';
book: Book;
books: Array<Book>;
booksWithTitle: Array<Book>;
user: UserResult;
};
export type QueryBookArgs = {
id: Scalars['ID'];
};
export type QueryBooksWithTitleArgs = {
title: Scalars['String'];
};
export type QueryUserArgs = {
username: Scalars['String'];
};
export type SuspendedUser = {
__typename?: 'SuspendedUser';
id: Scalars['ID'];
suspensionReason: Scalars['String'];
username: Scalars['String'];
};
export type User = {
__typename?: 'User';
id: Scalars['ID'];
username: Scalars['String'];
};
export type UserResult = SuspendedUser | User;
export type UserQueryVariables = Exact<{
username: Scalars['String'];
}>;
export type UserQuery = { __typename?: 'Query', result: { __typename?: 'SuspendedUser', id: string, username: string, suspensionReason: string } | { __typename?: 'User', id: string, username: string } };
export const UserDocument = gql`
query user($username: String!) {
result: user(username: $username) {
... on SuspendedUser {
id
username
suspensionReason
}
... on User {
id
username
}
}
}
`;
/**
* __useUserQuery__
*
* To run a query within a React component, call `useUserQuery` and pass it any options that fit your needs.
* When your component renders, `useUserQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useUserQuery({
* variables: {
* username: // value for 'username'
* },
* });
*/
export function useUserQuery(baseOptions: Apollo.QueryHookOptions<UserQuery, UserQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<UserQuery, UserQueryVariables>(UserDocument, options);
}
export function useUserLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<UserQuery, UserQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<UserQuery, UserQueryVariables>(UserDocument, options);
}
export type UserQueryHookResult = ReturnType<typeof useUserQuery>;
export type UserLazyQueryHookResult = ReturnType<typeof useUserLazyQuery>;
export type UserQueryResult = Apollo.QueryResult<UserQuery, UserQueryVariables>;

We can see that in lines 126–129, a new ...