Setting up GraphQL Subscriptions Using Apollo Client for React
Setup
This guide demonstrates how to set up GraphQL subscriptions using Apollo Client for React applications. It assumes you already have a basic Apollo Client setup according to the Apollo docs and now want to enable subscriptions.
Prerequisites
Installation
- Install the necessary packages:
npm install --save @apollo/client graphql-ws
- Import the required modules in the file where you initialized your client (usually your
App.js
file):
import { ApolloClient, HttpLink, InMemoryCache, split } from '@apollo/client';
import { GraphQLWsLink } from "@apollo/client/link/subscriptions";
import { createClient } from "graphql-ws";
import { getMainDefinition } from '@apollo/client/utilities';
- Initialize the client with the following configuration:
const httpLink = new HttpLink({
uri: 'https://<YOUR-HASURA-INSTANCE-URL>/v1/graphql'
});
const wsLink = new GraphQLWsLink(createClient({
url: 'wss://<YOUR-HASURA-INSTANCE-URL>/v1/graphql',
}));
const splitLink = split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink
);
const client = new ApolloClient({
link: splitLink,
cache: new InMemoryCache(),
});
This setup allows you to use queries and mutations over the defined httpLink
and subscriptions over the wsLink
through
the split function provided by the Apollo library. The split function takes a test function and two different links to
determine which link should be used to send the request.
This split link is then passed to the Apollo Client instance, which is then passed to the ApolloProvider
component
as per the basic Apollo setup.
Creating subscriptions
Switching to a subscription in Apollo Client is as simple as changing the useQuery
to useSubscription
hook and
switching the keyword in the graphql query from query
to subscription
.
For example, change the following query:
query GetProducts {
products {
id
name
price
}
}
to this subscription:
subscription GetProducts {
products {
id
name
price
}
}
When using this setup with Next.js, you will need to make sure that the wsLink
is only initialized on the
client and not while rendering on the server. To achieve this, you can test that you're in the browser with typeof
window !== 'undefined'
The wsLink
can be created as follows:
const wsLink = typeof window !== "undefined" ? new GraphQLWsLink(createClient({
url: 'ws://vast-fawn-54.hasura.app/v1/graphql',
})) : null;
and the splitLink
with a ternary as follows:
const link = typeof window !== "undefined" && wsLink != null
? split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink
) : httpLink;