React Apollo: Using Subscriptions

React Apollo: Using Subscriptions

After covering the basics in the first article, let's dig into more advanced use cases. This time we will check out how to utilize subscriptions in React Apollo. I will show examples in the form of a simple chat application. You can check the first part here:

When to use Subscriptions?

First things first, when do we need to use subscriptions? In Apollo documentation, it is stated that in the majority of cases you should not use subscriptions to stay up to date with the backend data. For this purpose, you should use polling or refetching. Using subscriptions is recommended in these cases:

  • Small, incremental changes to large objects. You can fetch the object's initial state with a query, and then push updates to individual fields as they occur.
  • Low-latency, real-time updates. The chat application is a good example of this use case. Users should see new messages as soon as they are received.

Defining Subscriptions

Subscriptions need to be defined on both the server side and the client side, the same as queries and mutations. To set up our chat application, we will define the following subscription, query, and mutation on the client side:

Let's see different ways to use subscriptions for fetching new messages in the chat application.

Followup Subscription

When we use the useQuery hook, we also get the subscribeToMore() function in the results. We can use this function to execute a followup GraphQL subscription that can push updates to our query's results.

In this example, we set up subscribeToMore() inside useEffect with empty dependencies array, which means this part of the code will be called when the component is mounted. For subscribeToMore() we pass two options: document and updateQuery.

For the document option we pass the subscription that needs to be executed. In this case, it is messageAddedSubscription GraphQL string, which listens for new messages.

Then, for updateQuery we pass the function that will update the cached results for the query. As arguments, we get prev, which represents queries currently cached data, and subscriptionData, which represents data returned from the subscription. The return value of this function replaces currently cached results for this query. In this example, we will append new messages that we get from the subscription to messages already present in the cache. This means that the data value that we get from the useQuery hook will be updated. In turn, this will cause re-render of the component and we will see new messages in the list.

Executing a Subscription with the Hook

We could also use useSubscription hook and then manually update cached results when we receive new data from the subscription.

In the above example, we pass onSubscriptionData handler to useSubscription hook. This represents a callback that will be called each time we receive data from the subscription. Then, we append data that we receive to the cache by using writeQuery method, available inside the Apollo client instance that we get in onSubscriptionDatamethod.

Conclusion

This article covered the basics about subscriptions in Apollo and ways to utilize them in your applications. They should be used in specific use cases only. Subscriptions are especially useful for low-latency updates and small incremental changes to large objects.