The goal of this chapter is to add realtime functionality to the app using GraphQL subscriptions. In particular, you’re going to make sure that when other users vote on a link, the link’s vote count updates immediately in the app for all other users without the need to refresh the page.
GraphQL subscriptions allow you to add event-based realtime functionality to your app. A client can subscribe to specific events that are happening on the server-side. Then, whenenever that event actually happens, the server will send the corresponding data over to the client.
Events usually refer to mutations, so typically we’re talking about events where data was created, updated or deleted.
Subscriptions are somewhat different from queries and mutations, since they don’t follow a request-response-cycle but instead represent a stream of data. The most common way to implement subscriptions is by using WebSockets, where the server maintains a steady connection to the subscribed clients that it uses to send over the data upon each event.
Subscription support was only added to Relay with the release of Relay Modern. Client can now use the requestSubscription
function to initiate a subscription.
requestSubscription
works very similar to the commitMutation
function as it also allows you to implement an updater
functions to specify how you want the cache to update based on the new data that was received from the server.
However, in order to get requestSubscription
to work, you also need to configure your Relay Environment
accordingly and provide the URL for your subscription endpoint. If subscriptions are implemented with WebSockets, the subscriptions URL will contain the wss
protocol instead of http
.
Graphcool generally exposes two different GraphQL APIs whose type definitions slitghly vary:
Currently, subscriptions are only supported for the Simple API. However, you can still use subscriptions with the Relay API by making some manual adjustments to the schema.graphql
which you feed into the relay-compiler
.
Notice that we already did these manual adjustments for you and you already have them in your project as you imported the project from this URL in chapter 3. If you’re interested in what these changes actually look like, take a look at the Subscription
type in schema.graphql
.
The first thing you need to do to get subscriptions to work is add websocket support to your project.
Note: We’re using a version 0.8.3 of the
subscriptions-transport-ws
package to be able to use theSubscriptionClient
. The tutorial will soon be updated to use the latest APIs.
This package contains the SubscriptionClient
that you need to setup subscriptions on the frontend. The SubscriptionClient
is a good fit in this case as it implements the same protocol as the subscriptions API from Graphcool.
Next you’ll have to configure your Relay Environment
and tell it about the additional endpoint that you want to use for subscriptions. The way how this works is actually by adding a second function to the creation of the Network
. This function knows about the subscription endpoint and is able to initiate and maintain a connection to it.
Let’s quickly understand what’s going on there:
Network.create()
, you just pull out the code of that closure and store it in a variable called fetchQuery
. Note that you’ll have to replace __PROJECT_ID__
again with your actual project ID. setupSubscription
that the Network
needs in order to be able to talk to the subscriptions endpoint. You’re using the SubscriptionClient
in that function to initiate and maintain a connection to the given endpoint. The config
that’s passed into the function carries the subscription query which determines what event the client wants to subscribe to and what data it wants to receive. Note that again you need to replace the placeholder for __PROJECT_ID__
with the actual ID of your Graphcool project. Also, you need to replace the placeholder for __REGION__
with the AWS region that your graphcool API endpoint is served from.fetchQuery
(which is the same code as before but stored in a variable) and setupSubscription
and use them to create the Network
, which then will be used to instantiate the Relay Environment
.If you’re not sure what your Graphcool project ID is that you need to replace the
__PROJECT_ID__
, you can openproject.graphcool
and check its frontmatter or executegraphcool endpoints
in a terminal to see the endpoints for the Relay API and Subscriptions API.To find the
__REGION__
your endpoint is served from, go to your Graphcool console. Click the Endpoints-button in the bottom-left corner, go toSubscriptions API
and replace__REGION__
with the region mentioned there (example: ‘wss://subscriptions.ap-northeast-1
.graph.cool/v1/PROJECT_ID‘)
Awesome, your app is now capable of using subscriptions! ⚡️
Similar to what you did with the mutations before, you’ll implement each subscription in a dedicated file to provide a more convenient wrapper around the requestSubscription
function that’s provided by Relay.
Let’s take a closer look at the subscription query that you’re storing in newVoteSubscription
first:
Vote
type.Vote
that was created, this information is represented by the node
field. Every time a vote is submitted by another user, the server will send information about that new vote, including the id
of the user
who created it and the total number of votes on the corresponding link (link._votesMeta
).requestSubscription
function. Notice that you’re using the updater
to increase the number of votes for the link that was voted on. Now that you have all required infrastructure setup, you can go ahead and actually iniate a subscription! For our project, it’s not too important where exactly the subscription is invoked as there are no context-dependent arguments that the subscription needs. However, it is important that the subscription only gets invoked once, so you don’t want to put it into the Link
component where it would be invoked as many times as Link
elements are rendered. You’ll therefore put it into the LinkList
component.
Then of course you also need to add the corresponding import.
Before you’re running the app, you’ll need to invoke the Relay Compiler again so it can compile the graphql
-tagged code inside NewVoteSubscription.js
.
All right, you can now run the app with yarn start
to test your subscription. The best way to test subscriptions is to use two different windows (or simply tabs) that are both running the app. If you then submit a vote in one window, the app should automatically update in the second window as well. 🎉