Using the GraphQL API
Once you have an access token, you can now use it to get (and push) data to/from Pitchly.
This step assumes you have generated an access token, which you will attach to every API request. Learn how to generate access tokens.
What is GraphQL?
GraphQL is a fairly new API framework that replaces the more common REST API. It was developed by Facebook to better handle data distribution at scale. We chose to use GraphQL for several of our own reasons:
Built-in subscription support enables Apps to get data in real time, a key design principle in Pitchly.
You can choose exactly the data you want to receive, spanning several possible data sets, in total fewer network requests.
It uses a single endpoint, creating less breaking changes, allowing for incremental adoptability and better version control.
If you are developing your App using a modern web application framework, we recommend using Apollo Client to work with our GraphQL API.
If you are not developing your App using a modern web application framework, you can still make calls to our GraphQL API over REST. This is because, at its core, GraphQL is really an abstraction over HTTP calls. It is a structured query language that gets sent over an HTTP request, just like REST, except the query is put inside the body of the request. Without a framework, like Apollo Client, however, you won't have the added perks of a client-side cache or automatic subscription updates.
On this page, we will be going over how to use the Pitchly GraphQL API using Apollo Client. To learn how to use Pitchly's GraphQL API over REST, visit our Client API.
Using Apollo Client
Apollo Client is compatible with several major frontend web frameworks, including React, Vue.js, Meteor, Angular, Ember, as well as native mobile on iOS and Android. You can get real snazzy with it, but we're just going to show a dirt basic example to start. The examples below are compatible with any frontend JavaScript framework you choose.
Basic query
Let's get information about the current database:
We will get back several properties of the database, including its name, description, color, and all of its fields, in the form of a Promise
.
This is great for a one-time query, but it only gives us a snapshot into a particular database on Pitchly in that moment. What if I want to be notified whenever the database changes?
Real-time subscriptions
Subscriptions are a feature of GraphQL that allow you to receive notifications of data changes on Pitchly as soon as they happen, over websockets.
We'll need just a few more NPM packages (we've included the ones above again):
We need to make some changes to the ApolloClient
:
Next, we will re-use the same query we initially had, but this time, we want to watch it change as new data from the subscription comes in. This will require two calls: one to the query and one to a subscription.
There are understandably a few confusing things here, so let's break it down.
There are two main differences between a query and a subscription:
A query retrieves a particular set of data.
A subscription is just a listener. It does not request any data when first connected, but only opens up a connection to get new data.
To make things even more interesting, there are also two different types of queries:
A normal query makes a single request and gets back a single response.
A watched query acts as a long-term "living" query, capable of long-term tasks like receiving subscription updates, refetches with updated variables, and continuous pagination.
The Apollo Cache
One important thing to know about Apollo is that queries do not hold the data they request in isolation. Under every query, subscription, and mutation is a single global cache that houses all requested data. The cache serves as a single source of truth for all requested API data, regardless of which query requested it.
The Apollo cache is global and semi-persistent, but don't confuse this with your browser's cache. Apollo's cache only lives inside the page session and does not carry across page reloads.
Subscriptions are able to function because the call to the subscription automatically "pulls down" updates into the Apollo cache when updated data arrives. Every watched query which uses that same data will automatically "pull up" the update from the cache.
This is great most of the time, but there may be cases where you want to do custom logic on a subscription update. Learn more below.
Observables
You may have noticed a lot of subscribes
floating around. Well, they're not all related to subscriptions.
An unfortunate choice of the makers of Apollo was to use the same method name for both creating GraphQL subscriptions and subscribing to their results from the Apollo cache. The first is a client-server intraction, while the latter is a client-client cache interaction.
Both client.watchQuery
and client.subscribe
methods return an Observable, which represents that query or subscription and the data it uses in the cache. When something changes to the data that query or subscription represents, you can capture that update by subscribing to its Observable. For subscriptions, subscribing to the Observable is necessary to tell Apollo you are interested in that data.
In addition to querying data, you can also perform actions against the Observable, such as refetching with different variables, checking load status, and paginating.
Remember that client.watchQuery
is not the same as client.query
. The first will return an Observable, whereas the latter will return a Promise because it is only run once.
After you are done with a set of data, make sure to unsubscribe from its updates using observerSub.unsubscribe()
, where observerSub
is the return value of observer.subscribe()
.
Mutations
Mutations are used whenever you want to "post" data to Pitchly, such as when you want to insert a row to a database. Mutations are very similar to queries in that they run once and return a Promise, but they also have some additional options.
This example will return the new row's _id
and cols
.
Mutations can do some unique things, like Optimistic UI, to keep latency at a minimum. But if you are using subscriptions, all of your queries using the affected data will be updated at near real time automatically after your mutation affects the relevant data, resulting in a positive UI loop. This makes for a very quick and seamless real-time experience for not only the user updating the data, but also for all other users viewing the same data. And it ensures that no user ever acts on data that is out of date.
More tips & tricks
Detecting load status
If you would like to get the loading status of a query with Apollo, perhaps to show a loading indicator, you can use the next
function in combination with notifyOnNetworkStatusChange: true
.
Note that subscribe
here is not related to Subscriptions, but rather it "subscribes" to an Observer.
In addition to detecting the load status of a watched query, next
can also be used to capture subscription updates, depending on your use case. Learn more.
Re-run a query with new variables
You can forcibly re-run a query by using refetch
.
This will make a new network request to Pitchly using the new variables for the query. The variables
object that is passed to refetch
is completely optional, and refetch
can be called alone to simply re-run the query with the existing variables intact.
Common use cases for refetch
are:
You are not using subscriptions and would like to manually re-query on an event or interval (if you are refetching on an interval, consider using
pollInterval
instead.)The access token, or another parameter, has changed and you need to update it
You need to re-capture a set of data for which there is no subscription
Change caching behavior
Caching in Apollo can be useful when dealing with repetitive queries against the same data. But sometimes it can make things difficult to debug, or Apollo may think you have all the data for an object because it already exists in the cache, when really you don't have all the data you need. If you're making a request for the same object but can't see the new data come in past the data you previously queried for, caching may be your issue.
There are several solutions, but a simple one is to change the caching behavior of a query by changing its fetchPolicy
. Just add it as an additional parameter to the query.
Possible options are:
cache-first
cache-and-network
network-only
cache-only
no-cache
standby
Read about each type of fetchPolicy
here.
fetchPolicy
can be applied to watchQuery
, query
, mutate
, and subscribe
operations.
Pagination
Pagination can be achieved without much manual effort using Apollo's fetchMore
function. Call fetchMore
the moment you would like to get more results.
Merging subscription updates
Subscriptions in Apollo are, by default, pretty smart. In most cases, they will merge new data into Apollo's cache for you, giving all your existing queries access to the new data automatically. But there are a few cases where this won't work:
The data coming from the subscription doesn't match the format of the data in the cache
A range of data was queried and a new row of data was created. We've been told about the new row, but we don't know where it is in relation to other rows (does it fit inside the range?)
Something new was created and we want to add it to our cache, but we didn't have a query for it previously because it didn't exist yet!
In these cases, either one of these two methods can help to update existing queries with new data:
refetch
Using refetch
simply runs the entire query again whenever we get notice from the subscription that something has changed. This method has pros and cons.
Pros:
Simplest way to keep data in sync
Maintains original sort order when getting an array of data
Automatically handles insertions and deletions
Cons:
Not very efficient, downloads entire results again and doubles network requests
Not suited for large or growing data sets (i.e. using infinite scroll). When querying a list of rows in a database, for example, you may not even be able to do a full refetch if you have used pagination to load more than the return limit (currently 100 rows at a time).
subscribeToMore
subscribeToMore
is similar to fetchMore
for pagination, except it can run multiple times for each update instead of only once, and is triggered by receipt of an update versus when you call it. It, too, has advantages and disadvantages.
Pros:
Fine-grained control over how the subscription updates the Apollo cache
Very efficient, does not make extraneous network requests, uses what it receives
Suited for large and growing data sets (i.e. using infinite scroll)
Cons:
More complicated to set up, subscription data (including insertions and deletions) must be merged manually
Doesn't maintain original sort order (hard to know where new items go)
Below is a real-world example of code we used in our Documents App to update documents with data in real time while also having infinite scroll through the use of fetchMore
. We additionally use Underscore.js and Meteor's client-side Collections here.
Query Batching
Pitchly supports query batching on all GraphQL API calls. Query batching allows multiple queries to be sent in a single request if they are executed very close together, saving valuable load time. This means that if you render several components, for example a navbar, sidebar, and content, and each of those do their own GraphQL query, they will all be sent in one roundtrip. In Apollo, it is very easy to enable query batching.
In your ApolloClient setup, replace the following section of code:
with:
Also make sure to install the NPM package:
See the Apollo Guide for more options around query batching.
References
Last updated