0
0
GraphqlHow-ToBeginner · 4 min read

How to Use Subscription with Apollo: Simple Guide

To use subscription with Apollo, define a GraphQL subscription query and use Apollo Client's useSubscription hook to listen for real-time data updates. On the server, set up a subscription resolver and a WebSocket connection to push updates to clients.
📐

Syntax

A GraphQL subscription is defined like a query but uses the subscription keyword. Apollo Client uses the useSubscription hook to subscribe to updates. The server needs a subscription resolver and WebSocket support.

  • subscription: Defines the subscription operation.
  • useSubscription: Apollo Client hook to listen for data changes.
  • Subscription resolver: Server function that pushes data updates.
graphql
subscription NewMessage {
  newMessage {
    id
    content
    sender
  }
}

// Apollo Client usage
import { useSubscription, gql } from '@apollo/client';

const NEW_MESSAGE_SUBSCRIPTION = gql`
  subscription NewMessage {
    newMessage {
      id
      content
      sender
    }
  }
`;

const { data, loading, error } = useSubscription(NEW_MESSAGE_SUBSCRIPTION);
💻

Example

This example shows a simple Apollo Client subscription to receive new chat messages in real-time. The server uses Apollo Server with WebSocket support to send updates.

javascript
// Server setup (Node.js with Apollo Server)
const { ApolloServer, gql, PubSub } = require('apollo-server');
const pubsub = new PubSub();
const NEW_MESSAGE = 'NEW_MESSAGE';

const typeDefs = gql`
  type Message {
    id: ID!
    content: String!
    sender: String!
  }

  type Subscription {
    newMessage: Message
  }

  type Query {
    _empty: String
  }
`;

const resolvers = {
  Subscription: {
    newMessage: {
      subscribe: () => pubsub.asyncIterator([NEW_MESSAGE])
    }
  }
};

const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {
  console.log(`Server ready at ${url}`);

  // Simulate sending a new message every 5 seconds
  let id = 1;
  setInterval(() => {
    pubsub.publish(NEW_MESSAGE, {
      newMessage: {
        id: id++,
        content: 'Hello at ' + new Date().toLocaleTimeString(),
        sender: 'Server'
      }
    });
  }, 5000);
});

// Client usage (React)
import React from 'react';
import { useSubscription, gql } from '@apollo/client';

const NEW_MESSAGE_SUBSCRIPTION = gql`
  subscription NewMessage {
    newMessage {
      id
      content
      sender
    }
  }
`;

function Messages() {
  const { data, loading, error } = useSubscription(NEW_MESSAGE_SUBSCRIPTION);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return (
    <div>
      <p>New message from {data.newMessage.sender}: {data.newMessage.content}</p>
    </div>
  );
}

export default Messages;
Output
Server ready at http://localhost:4000/ // Client UI updates every 5 seconds with new message like: // New message from Server: Hello at 10:15:30 AM
⚠️

Common Pitfalls

  • Not setting up WebSocket link on Apollo Client causes subscriptions to fail silently.
  • Forgetting to add Subscription type and resolver on the server.
  • Using HTTP link instead of WebSocket link for subscriptions.
  • Not handling loading and error states in useSubscription.
javascript
// Wrong: Using HttpLink for subscriptions
import { ApolloClient, HttpLink, InMemoryCache, split } from '@apollo/client';

const httpLink = new HttpLink({ uri: 'http://localhost:4000/graphql' });

const client = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache()
});

// Right: Use WebSocketLink and split for subscriptions
import { WebSocketLink } from '@apollo/client/link/ws';
import { getMainDefinition } from '@apollo/client/utilities';

const wsLink = new WebSocketLink({
  uri: 'ws://localhost:4000/graphql',
  options: { reconnect: true }
});

const splitLink = split(
  ({ query }) => {
    const definition = getMainDefinition(query);
    return (
      definition.kind === 'OperationDefinition' &&
      definition.operation === 'subscription'
    );
  },
  wsLink,
  httpLink
);

const clientCorrect = new ApolloClient({
  link: splitLink,
  cache: new InMemoryCache()
});
📊

Quick Reference

  • Define subscription: Use subscription keyword in GraphQL schema and queries.
  • Server resolver: Use PubSub or similar to publish events.
  • Apollo Client: Use useSubscription hook with WebSocket link.
  • Network setup: Use WebSocketLink and split to route subscriptions.

Key Takeaways

Use the subscription keyword to define real-time data operations in GraphQL.
Apollo Client requires a WebSocket link and the useSubscription hook to receive updates.
The server must implement subscription resolvers and publish events via a PubSub system.
Always handle loading and error states when using subscriptions in your UI.
Configure Apollo Client with split to separate subscription traffic from queries and mutations.