Realtime Updates with GraphQL Subscriptions

This section is all about bringing realtime functionality into the app by using GraphQL subscriptions.

What are GraphQL Subscriptions?

Subscriptions are a GraphQL feature allowing the server to send data to its clients when a specific event happens. Subscriptions are usually implemented with WebSockets, where the server holds a steady connection to the client. This means when working with subscriptions, you’re breaking the Request-Response-Cycle that was used for all previous interactions with the API. The client now initiates a steady connection with the server by specifying which event it is interested in. Every time this particular event then happens, the server uses the connection to push the expected data to the client.

Subscriptions with Apollo

When using Apollo, you need to configure your ApolloClient with information about the subscriptions endpoint. This is done by adding another ApolloLink to the Apollo middleware chain. This time, it’s the WebSocketLink from the apollo-link-ws package.

Go and add this dependency to your app first.

Next, make sure your ApolloClient instance knows about the subscription server.

Notice that you’re now also importing the split function from ‘apollo-link’.

You’re instantiating a WebSocketLink that knows the subscriptions endpoint. The subscriptions endpoint in this case is similar to the HTTP endpoint, except that it uses the ws instead of http protocol. Notice that you’re also authenticating the websocket connection with the user’s token that you retrieve from localStorage.

split is used to “route” a request to a specific middleware link. It takes three arguments, the first one is a test function which returns a boolean. The remaining two arguments are again of type ApolloLink. If test returns true, the request will be forwarded to the link passed as the second argument. If false, to the third one.

In your case, the test function is checking whether the requested operation is a subscription. If this is the case, it will be forwarded to the wsLink, otherwise (if it’s a query or mutation), the authLink.concat(httpLink) will take care of it:

Picture taken from Apollo Link: The modular GraphQL network stack by Evans Hauser

Subscribing to new links

For the app to update in realtime when new links are created, you need to subscribe to events that are happening on the Link type. There generally are three kinds of events you can subscribe to when using Prisma:

  • a new Link is created
  • an existing Link is updated
  • an existing Link is deleted

You’ll implement the subscription in the LinkList component since that’s where all the links are rendered.

Let’s understand what’s going on here! You’re using the <Query /> component as always but now you’re using subscribeToMore received as prop into the component’s render prop function. Calling _subscribeToNewLinks with it respective subscribeToMore function you make sure that the component actually subscribes to the events. This call opens up a websocket connection to the subscription server.

You’re passing two arguments to subscribeToMore:

  1. document: This represents the subscription query itself. In your case, the subscription will fire every time a new link is created.
  2. updateQuery: Similar to cache update prop, this function allows you to determine how the store should be updated with the information that was sent by the server after the event occurred. In fact, it follows exactly the same principle as a Redux reducer: It takes as arguments the previous state (of the query that subscribeToMore was called on) and the subscription data that’s sent by the server. You can then determine how to merge the subscription data into the existing state and return the updated data. All you’re doing inside updateQuery is retrieve the new link from the received subscriptionData, merge it into the existing list of links and return the result of this operation.

Awesome, that’s it! You can test your implementation by opening two browser windows. In the first window, you have your application running on http://localhost:3000/. The second window you use to open a Playground and send a post mutation. When you’re sending the mutation, you’ll see the app update in realtime! ⚡️

ATTENTION: There’s a currently a bug in the apollo-link-ws package that will prevent your app from running due to the following error: Module not found: Can't resolve 'subscriptions-transport-ws' in '/.../hackernews-react-apollo/node_modules/apollo-link-ws/lib' The workaround until it’s fixed is to manually install the subscriptions-transport-ws package with yarn add subscriptions-transport-ws. There’s also another bug in graphql-yoga which causes the subscription to fire multiple times (while the link is in fact only created once). After reloading the site, you’ll see the correct number of links.

Subscribing to new votes

Next you’ll subscribe to new votes that are submitted by other users so that the latest vote count is always visible in the app.

Similar as before, you’re calling subscribeToMore but now using NEW_VOTES_SUBSCRIPTION as document. This time you’re passing in a subscription that asks for newly created votes. When the subscription fires, Apollo Client automatically updates the link that was voted on.

Fantastic! Your app is now ready for realtime and will immediately update links and votes whenever they’re created by other users.

Unlock the next chapter
What transport does Apollo use to implement subscriptions?
WebSockets
TCP
UDP
HTTP 2