Overview
We're close to finishing up the data needed for the listing details page. Let's go ahead and add the amenities!
In this lesson, we will:
- Introduce the
Amenitytype to our schema - Build queries to display data for a listing and all of its amenities
Building the Amenity type
As we learned in the lesson on SDL syntax, fields on GraphQL types don't have to return a basic scalar type—they can also return other object types!
For instance, we can give our Listing type an amenities field—but what does this field actually return?
type Listing {id: ID!title: String!description: String!numOfBeds: Int!costPerNight: Float!closedForBookings: Booleanamenities: # What type should this be?}
Putting our business glasses on, we can see how more detailed data about an amenity—such as its id, name, what category it belongs to—would come in handy. The better or more descriptive the amenities a listing has to offer, the more motivated users might feel to make a booking! Furthermore, several listings might have the same kind of amenities; unlike an id or a title, a listing's amenities might not be unique to the listing itself!
For these reasons, we need to think of an "amenity" as a standalone entity—in other words, we should make it its own GraphQL type called Amenity.
This means that our Listing type should be updated: we need its amenities field to return a list of Amenity types!
Update your Listing type with the amenities description and field highlighted below.
type Listing {id: ID!title: String!description: String!numOfBeds: Int!costPerNight: Float!closedForBookings: Boolean"The amenities available for this listing"amenities: [Amenity!]!}
Now, let's actually define what an Amenity looks like. From our REST API responses, we know we can start with just a few properties: id, name, and category. In the schema.graphql file, add the new Amenity type shown below:
type Amenity {id: ID!"The amenity category the amenity belongs to"category: String!"The amenity's name"name: String!}
And from the schema's perspective, our work is done!
After saving our changes, the codegen process should have run automatically. We can check types.ts to make sure that our new Amenity type has been added!
export type Amenity = {__typename?: "Amenity";/** The amenity category the amenity belongs to */category: Scalars["String"]["output"];id: Scalars["ID"]["output"];/** The amenity's name */name: Scalars["String"]["output"];};
Testing the Amenity type
Jump back into the Explorer. We'll try running a query that calls for a listing's amenities details.
query GetListing($listingId: ID!) {listing(id: $listingId) {titlenumOfBedsamenities {namecategory}}}
And make sure that in the Variables panel, our $listingId variable is still set.
{ "listingId": "listing-1" }
And when we run the query... amenity data for our listing!
An alternate path
Now what about the featuredListings path? It's another entry point to our schema that returns a list of Listing types, for which we could then request the amenities field. Let's try it out.
query GetFeaturedListings {featuredListings {idtitledescriptionamenities {idnamecategory}}}
Uh-oh!
An error appears in the Response panel rather than the data we want. But what's the problem?
"Cannot return null for non-nullable field Amenity.name."
We were able to return amenities data for a single listing, but something's going wrong when we try to include it for each of our featured listings.
Key takeaways
- An object type's fields can return scalar types or other object types.
- When a field on an object type returns another object type, we can write complex queries that traverse from one object to another—no follow-up queries necessary!
Up next
Let's investigate the source of that error and fix it.
Share your questions and comments about this lesson
Your feedback helps us improve! If you're stuck or confused, let us know and we'll help you out. All comments are public and must follow the Apollo Code of Conduct. Note that comments that have been resolved or addressed may be removed.
You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.