GraphQL
Intro to GraphQL
What is GraphQL?
GraphQL is a specification for how to talk to an API. It's typically used over HTTP where the key idea is to POST
a "query" to an HTTP endpoint, instead of hitting different HTTP endpoints for different resources.
GraphQL is designed for developers of web/mobile apps (HTTP clients) to be able to make API calls to fetch the data they need from their backend APIs conveniently.
GraphQL vs REST: an example
Let's say you have an API to fetch a user's profile and their address. In a typical REST scenario, this is what the request/response would look like:
If your API server was a GraphQL server instead, this is what your API calls would look like:
You can see that the response JSON is different for different "queries" sent by the client.
Thinking in GraphQL
We're changing the way we think about API calls. Instead of making different API calls to different URLs to fetch data, we're making ad-hoc queries to a "single URL endpoint" that returns data based on the query.
Instead of 'GET'ing a resource you 'POST' a query that describes what data you want.
You think of the data your API returns as a "graph", this allows you to make queries to fetch "related" pieces of data in a single shot. In the example above, you fetch the user and the user's address (as a nested JSON object) in the same API call, as opposed to making 2 API calls.
The "query" you send as data in the POST request has a structure and a syntax. This "language" is called GraphQL.
As you can see in the example above, GraphQL queries look very neat and easy to read! This is because the query is the "shape" of the final JSON data you desire. This is one of the key-reasons that makes GraphQL a joy to work with!
GraphQL benefits
Avoid over-fetching: You avoid fetching more data than you need because you can specify the exact fields you need.
Prevent multiple API calls: In case you need more data, you can also avoid making multiple calls to your API. In the case above, you don't need to make 2 API calls to fetch
user
andaddress
separately.Lesser communication with API developers: Sometimes to fetch the exact data you need, especially if you need to fetch more data and want to avoid multiple API calls, you will need to ask your API developers to build a new API. With GraphQL, your work is independent of the API team! This allows you to work faster on your app.
Self-documenting: Every GraphQL API conforms to a "schema" which is the graph data model and what kinds of queries a client can make. This allows the community to build lots of cool tools to explore & visualise your API or create IDE plugins that autocomplete your GraphQL queries and even do "codegen". We'll understand this in more detail later!
Here's a quick chart to show you the GraphQL analogs of typical REST-ish terms:
Try out GraphQL queries
For this tutorial we've set up a GraphQL API for you. The most common way to browse a GraphQL API is to use GraphiQL. GraphiQL is a tool built by Facebook, (pronounced "graphical") that makes it easy to explore any GraphQL API.
When you connect GraphiQL to a GraphQL endpoint, it queries the server for its GraphQL schema and gives you a UI to browse and test queries, and that powers its amazing autocomplete!
Tools like GraphiQL make GraphQL APIs really easy to use and integrate APIs in your app without requiring external documentation tools.
You can access the GraphiQL for this realtime todo app tutorial here: hasura.io/learn/graphql/graphiql
When you work with a GraphQL API in a project you will almost always use a tool like GraphiQL to explore and test your GraphQL queries.
Basic GraphQL query
Open GraphiQL at: hasura.io/learn/graphql/graphiql. You'll have to login to get an auth token to query the API. In a real-world scenario your GraphQL APIs will be protected.
You'll see a URL, and headers that contain the auth token that will be sent along with your GraphQL query.
Now, paste this GraphQL query in the GraphiQL window
Hit
ctrl + enter
orcmd + enter
(mac) or click on the ▶️ icon to run the GraphQL queryOn the right, you should see a list of users by their names that are in the system!
Recall that there is no magic here! The hosted GraphiQL app is sending a GraphQL query string to the server at the given endpoint with the HTTP headers. The server then sends the response that you see on the right hand side.
Fetching "graphs"
Our todo app has users, todos and information about users that are currently online. This is what our API "schema" looks like:
As you can see, it is a "graph" like schema where all the 3 models are linked to each other.
Let's try making queries that fetch different slices of our data from the overall "graph".
Fetch users and their todos
This GraphQL query will fetch all the users and their publicly visible todos:
Fetch online users and their profile information
This GraphQL query will fetch all the currently online users and their profile information (which is just their name for now):
Adding parameters (arguments) to GraphQL queries
In most API calls, you usually use parameters. For example, to specify what data you're fetching. If you're familiar with making GET
calls, you would have used a query parameter. For example, to fetch only 10 todos you might have made this API call: GET /api/todos?limit=10
.
The GraphQL query analog of this is arguments that you can attach to a "field".
Basic argument: Fetch 10 todos
This GraphQL query will fetch 10 todos and not all of them.
The most important bit to check here is limit: 10
. GraphQL servers will provide a list of arguments that can be used in ()
next to specific fields. In our case, we are using Hasura for creating the GraphQL backend which provides filter, sort and pagination arguments. The GraphQL server or API that you use, might provide a different set of arguments that can be used.
Multiple arguments on multiple fields: Fetch 1 user and 5 most recent todos for each user
Notice that we are passing arguments to different fields. This GraphQL query reads as:
Fetch users (with limit 1), and their todos (ordered by descending creation time, and limited to 5).
GraphQL variables: Passing arguments to your queries dynamically
This is great, but we still have a problem. If we want to create a query where we are fetching data with arguments that are provided dynamically, we'd have to create the entire query string again.
This is what we don't want to do:
Thankfully, we don't ever have to do this! GraphQL variables are extra variables that you can send in a query so that the "arguments" can be provided dynamically!
Fetch $limit number of todos
This is what our GraphQL query would look like:
In addition to the query above, we send a variables object:
Now instead of sending just the query to the GraphQL server, from our client we'll send both the query and the variables. The GraphQL server will use the variable in the right place in the query automatically for us!
Let's try this out in GraphiQL:
Head to GraphiQL
Write out this query
Scroll to the bottom of the page, where you see a smaller panel "Query Variables"
Add the query variable as a JSON object
Summary
You can now make GraphQL queries
You know how to pass arguments to your GraphQL queries
You know how to make your arguments dynamic by using query variables
Next, let's look at writing data and not just fetching data!
Architecture
GraphQL over HTTP
Check out the diagram below, to get a sense of how GraphQL is typically used in your stack:
GraphQL client-server flow:
Note that the GraphQL query is not really JSON; it looks like the shape of the JSON you want. So when we make a 'POST' request to send our GraphQL query to the server, it is sent as a "string" by the client.
The server gets the JSON object and extracts the query string. As per the GraphQL syntax and the graph data model (GraphQL schema), the server processes and validates the GraphQL query.
Just like a typical API server, the GraphQL API server then makes calls to a database or other services to fetch the data that the client requested.
The server then takes the data and returns it to the client in a JSON object.
Example GraphQL client setup:
In your day to day work, you don't actually need to worry about the underlying HTTP requests & responses.
Just like when you work with a REST API and use a HTTP client to reduce the boilerplate in making API calls and handling responses, you can choose a GraphQL client to make writing GraphQL queries, sending them and handling responses much easier.
In fact, the mechanism of how you send the GraphQL query and accept the GraphQL response has become standard. This makes working with GraphQL very easy on the client.
Here's what a typical GraphQL client setup and making a query would look like:
Writing data - Mutations
These are the concepts you should know before you attack mutations (haha):
Now, let's get started with seeing how we can use GraphQL to "write" data. GraphQL mutations are types of GraphQL queries that may result in the state of your backend "mutating" or changing, just like typical 'POST'
, 'PUT'
, 'PATCH'
, 'DELETE'
APIs.
Basic mutations
Since we're using Hasura for our GraphQL API, we get mutations for inserts, updates or deletes that we can use in our app.
Let's try these mutations out in the context of a todo app to see what mutations look like. Mutations that you get from another GraphQL service, say if your API team has built their own, might be different.
Create a todo
Let's make an API call to create a todo. As you would have guessed, this will be a critical portion of our todo app. 😉
Protip: Now let's say we don't know what the name of the mutation to create a todo. GraphiQL to the rescue! Head to GraphiQL and on the right, click on the "docs" tab. Type "todo" there and you'll see a list of GraphQL queries and types that use todo. Read through their descriptions and you'll soon find that
insert_todos
is what you need.
The mutation to create todos is titled insert_todos
.
Returning data after the mutation
Notice that the data of the todo that is to be inserted is sent as an argument to the insert_todos
mutation. But the "fields" of the mutation specify the shape of the response that you want from the server.
Let's say we'd like to get the entire todo object once it's been created as a response:
Parameterise what you insert
For mutations, we would almost always have to parameterise the arguments! We would rarely, if ever, have a "hardcoded" mutation in our app. This is because the arguments of what data to capture, how to modify or delete something is usually dependent on some user action.
Now that we know how to parameterise using query variables, let's use that:
We'll explore more mutations to update or delete data a little later. This is a good start to grokking mutations!
Summary
You can make basic GraphQL mutations
You can pass dynamic arguments/data to mutations with query variables
Next, let's look at GraphQL subscriptions
Watching data - Subscriptions
The GraphQL specification allows for something called subscriptions that are like GraphQL queries but instead of returning data in one read, you get data pushed from the server.
This is useful for your app to subscribe to "events" or "live results" from the backend, but while allowing you to control the "shape" of the event from your app.
GraphQL subscriptions are a critical component of adding realtime or reactive features to your apps easily. GraphQL clients and servers that support subscriptions are great because they allow you to build great experiences without having to deal with websocket code!
Make your first GraphQL subscription
Step 1: Head to https://hasura.io/learn/graphql/graphiql Step 2: Write this GraphQL query in the textarea:
Step 3: Click on the play button.
Every time the set of online users change, you'll see the latest set on the response window on the right.
How do GraphQL subscriptions work?
GraphQL queries and mutations are strings sent to a POST endpoint. What is a GraphQL subscription? That can't happen over a POST endpoint, because a simple HTTP endpoint would just return the response and the connection would close.
A GraphQL subscription is a subscription query string sent to a websocket endpoint. And whenever data changes on the backend, new data is pushed over websockets from the server to the client.
Summary
You know how to make GraphQL subscriptions
Get Started with GraphQL Now
Last updated