DEV Community

Peter Kang
Peter Kang

Posted on

Exploring GraphQL

As I broaden my developer skillset, I've discovered that reiterating is a great method of reinforcing what I learned, and writing is one of the best mediums to do so. Thank you for visiting and I hope that you're able to take something away from this as well!

What is GraphQL?

GraphQL is a query language that was created by Facebook to address the data fetching challenges faced when attempting to get data from server to client. Contrary to popular belief, it can be used with many programming languages to implement a graph server.

GraphQL vs REST API

Generally, fetching large amounts of data from REST API's may end up tricky since requests may use many different endpoints, resulting in a unsavory response time.

With GraphQL, we can define and send a query to a GraphQL server. A query looks similar to a JSON object. Let's say we want to get the data of a certain Pokémon. An example query would look like this:

{ 
  pokemon {
    name
    type
  }
}
Enter fullscreen mode Exit fullscreen mode

The response looks similar to the query:

{ 
  "data": {
    "pokemon" {
      "name": "blastoise"
      "type": "water"
     }
  }
}
Enter fullscreen mode Exit fullscreen mode

As we change the data that we need, we can update query by adding to it. It is nested and issued at once! For example, we can add more fields after type and there may even be more nested fields after that.

One benefit that came to mind was loading UI components. We can utilize one call to get the data that we need and populate the component accordingly! So neat.

For a more in-depth look (and quite frankly a much better explanation than I can provide at the moment) into REST vs GraphQL, I've found that this video does an excellent job.

Let's Try It! Github API/GraphiQL

To try it out, we'll be using Github's GraphQL API and the GraphiQL interface. This is essentially an in-browser IDE that allows us to make queries to the Github API. We can get started here. We will need to be signed into a Github account, or make one if you don't have one yet. Both can be accomplished here.

Queries

When we build queries, we ask for the values of fields. The most basic field we can start with in the Github GraphQL Explorer is the viewer field, like so:

{
  viewer {

  }
}
Enter fullscreen mode Exit fullscreen mode

Within viewer, we can add a subfield of login by nesting it within viewer.

{
  viewer {
    login
  }
}
Enter fullscreen mode Exit fullscreen mode

We can hit the button that looks like the "play" symbol and the query will be sent to the server. The response looks very similar to a JSON object. If you have a username set up in your Github settings, it should be returned here. Otherwise, it may return null.

Alt Text

In addition, you'll notice that there is some auto-complete behavior when entering fields. We can also access all the possible fields by hitting ctrl + space. Try playing around with all the possible fields we can explore!

Alt Text

Let's get some more information like our bio, id, and profile picture. We can get this data by entering the fields name, bio, and avatarURL.

Alt Text

Arguments

There are fields that can be take arguments. For example repositoryOwner can take arguments to return data about just that. We can see that it takes login as an argument. Let's look up Facebook, its id, its path (the subfield is referred to as resourcePath), and its url. Please note that in GraphQL, we must use double quotes.

Alt Text

Some fields require arguments. Such a field is the repository field. We can see that the name and owner arguments are required since those two pieces of information are required to get a single repository. Let's look up GraphQL's GraphiQL repository and get its description.

Alt Text

Any attempts to make queries without required arguments will result in an error. For example, if we try to query repository without the owner argument, we would get the following error:

Alt Text

Schemas

Fields are determined by GraphQL schemas. These schemas provide the object types used in our data, and they specify the types for all the values. An advantage of using the GraphiQL interface is that the schemas are well documented in the browser.

In the Github GraphiQL interface, if we click on Docs on the right side, we can see the available schemas.

Alt Text

We have two root types, query and mutations the latter which we will go over later on.

Alt Text

If we click query we are met with a list of all the possible fields that we can use.

Alt Text

Let's scroll down and click the repository field. Once we do, we can see that it has two arguments, name and owner. They are specified to have a String type and the exclamation point denotes that they are required arguments.

Alt Text

Try exploring the query schema and all the fields we can explore in the Github GraphQL API.

Querying __schema

What if we are outside the GraphiQL interface? We can query __schema to check out the architecture and all the possible values. Let's do just that. We will query __schema, and from there we will choose queryType, which is one of two root types in the schema. In queryType, we will query name, description, and fields. Finally, within fields, we will query name and description once more. The resulting query and response will look like this:

Alt Text

Note that there is a description of the root query type. After that, the response lists all the possible fields we can utilize with their names and description. Neat!

Aliases

Let's say that we want to query two repositories. We can utilize aliases to do so. For example we will query for the react-native and create-react-app repositories. In this case, I will give them aliases as reactNativeRepo and createReactAppRepo, respectively. Each of them will be followed by a colon, and their respective queries. In these queries, let's look for their respective names, descriptions, and URLs. They will be nested in one big query, like so:

Alt Text

Fragments

Note that in our previous query, we are querying the same three fields. This doesn't seem like very DRY code, so we can utilize fragments. We can utilize fragments to shorten our code a bit and have reusable bits of our queries. The fragment will take this form:

fragment fragmentName on objectType {
  fields
}
Enter fullscreen mode Exit fullscreen mode

So, in our case, our fragment will look like this:

fragment repoInfo on Repository {
  id
  description
  homepageUrl
}
Enter fullscreen mode Exit fullscreen mode

Finally, we can include our fragment with a spread operator before it in our query. It will look like this:

Alt Text

Nice! We now have a reusable bit of query that we can use elsewhere without repeating the same fields.

Nested Fields

Let's say we have the following query:

{
  viewer {
     id
     name
     location
     repositories
  }
}
Enter fullscreen mode Exit fullscreen mode

We will get the following response:

Alt Text

edges indicates a connection to another array of data. The field node in this case represents a single repository. In addition, you'll notice the error message,

You must provide a first or last value to properly paginate the repositories connection.

Here, we must pass in an argument into repositories so that the server knows which repositories to look for. I'll pass in last: 3 to get the last three repositories, as well as name in the node field to get their names.

Alt Text

Check out the other arguments for repositories for other ways you can query the repos! In addition, explore the repositories field in the Docs and take note of what you see there.

We can make a fairly complex query with multiple nested fields. The beauty of it is that we can grab large amount of data with just one call!

Operation Names

We can add the word query at the beginning of our queries. It will function the same way. However, in a codebase of complex queries, it may be hard to keep track of. As a result, we can add the word query followed by an identifying name.

For example, let's give our previous query a name of getLastRepos. In addition, I'll duplicate the query and instead get the first three repos. This will be named getFirstRepos.

Alt Text

As a result, when we hit the play button to make the queries, we are given options to query because of the operation names we gave our queries. This can be deeply useful when we have many queries!

Alt Text

Variables

Let's now explore the organization field. I have the following query that search Facebooks first three members.

{
  organization(login:"facebook") {
    id
    name
    membersWithRole(first: 3) {
      edges {
        node {
          id
          name
        }
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

However, we can use variables to search other organizations using variables. First, let's reformat our query. First, we'll give our operation a clear name. Next, we'll pass in $login: String! to our operation which indicates that the login variable will be a String type and that is required.
Next, in the organization field, we'll replace "facebook" with login.

query getFirstThreeMembers($login: String!){
  organization(login: $login) {
    id
    name
    membersWithRole(first: 3) {
      edges {
        node {
          id
          name
        }
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, where do we define these variables? At the bottom of the interface, we notice a section we haven't used yet, Query Variables. Let's bring it up.

Alt Text

In there, we will define login, and this time we'll set it to "google". As a result, the first three members of Google's organization in Github will return in the response.

Alt Text

Awesome!

Mutations

We've gotten data thus far, but how do we change it? In GraphQL we will utilize mutations. We can think of mutations as similar to PUT or DELETE requests when working with REST APIs. In GraphQL, we can send data as a payload in a mutation. The dataset is changed, and the API defines which mutations can be performed. Check out the Docs in the Github GraphiQL to see which mutations we can perform.

For our demonstration purposes, I will be using a mutation to create an issue in one of my repositories. For these purposes, I've created a repository named graphql-tests. Its issues tab will can be found here.

I will write a query to find this repo and its ID, which we will need to make our mutation. Keep this ID closeby!

Alt Text

Next, we'll write our mutation query. We will start with the mutation type, and give it a name, createIssue. If we explore the docs for creating a new issue via mutation, we'll see that the payload consists of a clientMutationId and issue. We will create an input variable that contains our payload.

Next, we will enter the createIssue field with input: $input as arguments. It will contain the aforementioned clientMutationId and issue, and within issue, we'll include id, body, and title.

Alt Text

Excellent! Now all we have to do is define our input variable.

The input payload has two requirements, a unique clientMutationId which we can set to whatever we'd like, and the repositoryId which we got from our first query. In addition, we included body and title in our mutation query so let's include that as well.

Alt Text

Here is a look at our query, variable, and response:

Alt Text

And finally, if we take a look at the repository on Github, we can see that the issue was created.

Alt Text

Awesome! There are so many different mutations we can perform with this API alone. Each GraphQL API will have its queries and mutations documented so the possibilities are endless!

Conclusion

I hope that this article provided you with some value and a way to get your feet wet with GraphQL. Writing it has been a great way to reinforce what I've learned thus far. Thank you for taking the time to read and explore.

If you'd like to connect, reach me here:

Top comments (0)