GraphQL: Learn by Doing (Part 3 of 3)

Armand Aquino
EdgeCoders

--

This is the last story for the 3 part series GraphQLLearn by Doing” series.

Hope you enjoyed Part 1 and 2 and have a working GraphQL server and can query the GitHub API. Let’s take it to the next level.

We last left off by taking the results from a GitHub API call and mapped each field that is returned. We also modified some of the fields so the developer and app have to do less work. Now we‘ll add new fields so the developer and app have to do even less work. Great, right?

Let’s just say that based on the data returned from the GitHub API call that we don’t just want to display the URL to get the information on the users a particular user is following but we want to get the actual information on those users as well. We want to display all the information on the current view and not have to pass that data to another component to make another API call or the user has to perform some action to display the data so we can lazy load the data. We want all the data for the initial render. Ok? Got it.

Since we have access to the data that is returned from the original data source and can add new fields, let’s add a new field to the UserInfoType that resolves the information we want by making another RESTful API call.

We need to create a new type with the fields that are available when calling the URL from “following_url” and create a new field with that type and resolve it by calling another API call.

I will not go through making that other type because you should be able to to do that by now. Run the API query again and make a new type based on the output. As usual, the link to the repo will be provided at the end of this article. There will be room to make the code DRY but that can be done another time in a future sprint.

The one thing you will notice when you see the results from that API call is that it is an array of objects with fields of that new type we just created. We will use a new type that we may not have seen before: “new GraphQLList()”. That is simply an object that expect a list of objects, or an object that is iterable like an array, of the certain GraphQL object type. Here is the sample code with the new field we will add to the UserInfoType.

...
“users_following”: {
type: new GraphQLList(RepoInfoType),
resolve: (obj) => {
const brackIndex = obj.following_url.indexOf(“{“),
url = obj.following_url.slice(0, brackIndex);
return axios.get(url)
.then(function(response) {
return response.data;
});
}
},
...
  • Add new “users_following” field to the UserInfoType
  • Declare the type to be a list of the new type “RepoInfoType” (need to create)
  • Re-implement the logic to trim the “following_url” because we only get the the object returned by the data source - not how GraphQL resolve/returns it or new fields that we added. We can refactor this to keep it DRY if we want to in the future.
  • Call axios again with the URL string.

Here is a screenshot of the udpated query in GraphiQL

Now we don’t have to make another API call because we under-fetched. I would like to point out that it still needs to be done somewhere but why should the client do it? Let’s make the client have a smaller footprint, get only the data it needs, and do less work. The GraphQL server will probably be on better hardware equipped to handle more data call and execute functions faster and more efficiently.

The other interesting part is you can design this to nest deeper into the “users_following” because you can call it again to see information on the users of the users the original user you are querying for is following. Hope I didn’t lose you there so below is a screenshot. Watch out though because you can get rate-limited by GitHub on this if you go crazy deep, I did. If that was your requirement for some reason, you can get it on one round-trip!

As you add more types you will notice that you repeat a lot of fields. We can DRY up this code a few ways. Since this is JavaScript and the fields just expect objects, you can write a function that returns an object with the configuration you need. Here is some of the code you can write to re-use common fields in the types. Your code will look much cleaner.

// Common fields
function usersFollowing() {
return {
type: new GraphQLList(RepoInfoType),
description: “Fields about the people you this person follows”,
resolve: (obj) => {
const brackIndex = obj.following_url.indexOf(“{“),
url = obj.following_url.slice(0, brackIndex);
return axios.get(url)
.then(function(response) {
return response.data;
});
}
};
}
// Added field in the UserInfoType...
“users_following”: usersFollowing(),

This was just an easy implementation of GitHub on GraphQL to serve as an intro to get your feet wet. There are other things that can be done to make it more scalable, re-usable, and have more functionality. For example, using some features to prepare it for relayjs, an awesome framework by Facebook that uses GraphQL, will allow you to have functionality for pagination and handle nesting better.

Last thing I will show you is how to make queries to a GraphQL server from your React app. There are many ways to do this in a React app: In the componentWillMount lifecycle method or in an API call in the actions in Flux/Redux. You also have different XHR libraries to choose from like axios, fetch, or jquery. I will use axios in this example.

axios.post(‘/graphql’, {
query: `
{
gitHubUser(username:”${login}”) {
login,
avatar_url,
following
following_url,
location,
users_following {
login,
avatar_url
}
}
}
`
})
.then( response => {
// response from axios comes with a data object and so does graphql // that is why there is data.data.
// you can call another function here or if this is in a component you can call setState.
return response.data.data;
});

In this example, we create a query object that is passed to axios and it’s set to a string template that builds the GraphQL query. It expects the variable “login” to be set somewhere in the code, usually a variable in props or state. The one thing I want to point out here is that I use the “post” method here instead of “get” which is usually used for fetching data with RESTful API calls. That is because the “query” object I call is not just a url and can get very long. Using “get” has a limit of ~2000 characters because of the URL maximum length limit. You can unknowingly go over that limit using “get” query parameters and you don’t want to always check the length before you make the call. So I just use “post” all the time.

Here is a link to the repo. It is not a complete implementation and not much work will be done on it in the near future so I can work on other GraphQL and Relay blog posts. However, feel free to fork, update, and make a PR, pull request if you want build on top of this and share it everyone.

Hope you found this series informative and learned more about GraphQL by doing. It was a joy to write because I think GraphQL is awesome sauce.

If you thought this article was helpful, then consider recommending ❤ the story so more people will find it.

--

--

Armand Aquino
EdgeCoders

Quantitative Analyst/Developer at Optimal Asset Management, Inc. ✌♠️