In src/resolvers.js
, in our tracksForHome
resolver, let's add the parameters.
The order of the parameters matters here. If we only added one parameter, then the function would consider it as the first optional parameter: parent
. We need the contextValue
, which is the third parameter, to access our data sources.
We don't need the first two parameters, so as a convention, we'll name them with underscores: one underscore for the first (parent
) and two underscores for the second (args
).
For the contextValue
, we'll destructure it to access its child object dataSources
. And we can omit the fourth parameter, info
, as we won't use it.
const resolvers = {Query: {// get all tracks, will be used to populate the homepage grid of our web clienttracksForHome: (_, __, { dataSources }) => {},},};
Edit the parameters for the resolver function of the spaceCats
field to follow the conventions explained above. You'll need to destructure dataSources
from the contextValue
parameter. The function should not return anything for now.
From our dataSources
object, we'll gain access to our trackAPI
(lowercase here as it's the instance of our TrackAPI
class extending RESTDataSource
) and its getTracksforHome
method that we built earlier.
Our tracksForHome
resolver will return the results from that TrackAPI
method.
const resolvers = {Query: {// get all tracks, will be used to populate the homepage grid of our web clienttracksForHome: (_, __, { dataSources }) => {return dataSources.trackAPI.getTracksForHome();},},};module.exports = resolvers;
Create a resolver function for the Query.spaceCats
field. Follow the conventions explained above for the four optional parameters. Use the dataSources
object to access the spaceCatsAPI.getSpaceCats()
method and return the results. Use arrow function syntax.
Now, that takes care of getting the data for our tracks, but we also need the author associated with each track. We need to call the getAuthor
method from our TrackAPI
.
So where should this call be located? Well, our tracksForHome
resolver could map over the returned tracks data, take each track's authorId
property, and call getAuthor
with it. But then our tracksForHome
resolver would always fetch author data, even for queries that don't even request it!
Instead, let's add another resolver specifically for a track's author. To do this, we'll add another key to our resolvers
object called Track
, indicating that it's for the Track
type in our schema. Inside that Track
key will be another object with an author
field, where we'll define our resolver.
const resolvers = {Query: {// ...},Track: {author: (parent, args, contextValue, info) => {},},};
This time we'll need the parent
argument, so let's keep it in the resolver function. We can replace args
with an underscore. We'll destructure contextValue
to access the dataSources
key for our TrackAPI. And then omit info
because we don't need it.
const resolvers = {Query: {// ...},Track: {author: (parent, _, { dataSources }) => {},},};
The TrackAPI
's getAuthor
method needs an authorId
. We'll get this value from the parent
argument passed to the resolver. The parent
argument contains data returned by our tracksForHome
resolver, and because tracksForHome
returns a list, Apollo Server iterates through that list and calls the author
resolver once for each track. It passes the current track as the value of parent
, enabling us to extract the authorId
.
If we were to console.log(parent)
, inside our author
resolver, the printed value would look exactly like a single raw track from the tracks list returned by our RESTDataSource
.
parent
argument of our Track.author
resolver?Let's destructure authorId
from the parent
argument. Then, we'll call the getAuthor
method from our dataSources.trackAPI
method, passing in the authorId
. Finally, we'll return the result.
const resolvers = {Query: {// get all tracks, will be used to populate the homepage grid of our web clienttracksForHome: (_, __, { dataSources }) => {return dataSources.trackAPI.getTracksForHome();},},Track: {author: ({ authorId }, _, { dataSources }) => {return dataSources.trackAPI.getAuthor(authorId);},},};
Create a resolver function for the SpaceCat.missions
field. Follow the conventions explained above for the four optional parameters. Use the dataSources
object to access the spaceCatsAPI.getMissions()
method. It takes a catId
argument from the parent
and returns the results. Use arrow function syntax.
As a best practice, when working on your resolvers and data sources, try to keep resolver functions as thin as possible. By doing so, you make your API more resilient to future changes. You can safely refactor your data fetching code, or change the source entirely from a REST API to a database, without breaking your API. This also keeps your resolvers readable and easier to understand, which comes in handy as you define more and more of them!
Now, you might be wondering where the dataSources
object that's passed to our resolver comes from. When did we add it to the contextValue
parameter? Right now, it isn't added. If we ran our server, it would have no clue about our TrackAPI
. It also doesn't know about our resolvers yet! Let's make sure all three pieces are connected with each other.
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.