Building React Real-Time Apps with GraphQL Subscriptions (Chat & Live Feed Guide)
Solidly Stated presents a practical react graphql subscriptions example for implementing real-time chat or a live activity feed with a modern React stack.
Why Real-Time Features Matter in Modern Apps
Users expect instant updates when they send a message or watch a live feed. Waiting for manual refresh feels slow and outdated. Real-time communication increases engagement and makes collaboration smoother.
GraphQL Subscriptions offer an elegant solution for these needs. They open a persistent connection and push new data to the client when events happen on the server.
With a clean react graphql subscriptions example, developers can avoid complicated polling logic and reduce unnecessary network traffic.
Core Architecture for a Real-Time React App
A solid real-time architecture relies on a few core building blocks. These components work together to deliver instant updates to the browser.
First, the GraphQL server defines subscription fields on the schema. These fields describe which events clients can listen to.
Second, a PubSub or message broker layer broadcasts events inside the backend. Each new message or feed item triggers a publish operation.
Third, the React client connects using WebSockets instead of plain HTTP. The browser stays connected and receives pushed data quickly.
This layered design keeps the react graphql subscriptions example modular and easy to extend.
Designing the GraphQL Schema for Chat and Feed
A good schema keeps the client API simple. For a basic chat or live feed, only a few types are required.
The core types often include a Message type, a FeedItem type, and a Subscription type. Queries still fetch history, while mutations create new entries.
Below is a schema outline that fits a standard react graphql subscriptions example:
type Message {
id: ID!
text: String!
author: String!
createdAt: String!
}
type FeedItem {
id: ID!
content: String!
type: String!
createdAt: String!
}
type Query {
messages: [Message!]!
feed: [FeedItem!]!
}
type Mutation {
sendMessage(text: String!, author: String!): Message!
addFeedItem(content: String!, type: String!): FeedItem!
}
type Subscription {
messageAdded: Message!
feedItemAdded: FeedItem!
}
With this structure, a single backend can power both chat and activity feed views in React.
Implementing Subscriptions on the GraphQL Server
On the server, Subscriptions need a WebSocket-aware GraphQL transport plus a PubSub mechanism. Many tutorials use a simple in-memory PubSub for small demos.
Resolvers for subscriptions return an async iterator. Each publish event pushes the payload to connected clients.
Below is the heart of the react graphql subscriptions example on the backend:
const { PubSub } = require('graphql-subscriptions');
const pubsub = new PubSub();
const resolvers = {
Mutation: {
sendMessage: async (_, { text, author }) => {
const message = { id: Date.now().toString(), text, author, createdAt: new Date().toISOString() };
// Save to DB here
await pubsub.publish('MESSAGE_ADDED', { messageAdded: message });
return message;
},
addFeedItem: async (_, { content, type }) => {
const item = { id: Date.now().toString(), content, type, createdAt: new Date().toISOString() };
// Save to DB here
await pubsub.publish('FEED_ITEM_ADDED', { feedItemAdded: item });
return item;
}
},
Subscription: {
messageAdded: {
subscribe: () => pubsub.asyncIterator('MESSAGE_ADDED')
},
feedItemAdded: {
subscribe: () => pubsub.asyncIterator('FEED_ITEM_ADDED')
}
}
};
This pattern keeps the react graphql subscriptions example clear and focused.
Setting Up the WebSocket Transport Layer
To support subscriptions, the GraphQL endpoint must accept WebSocket connections. Many stacks use Apollo Server or similar tools for this job.
A common approach is to run HTTP and WebSocket on the same URL. The server distinguishes protocols during the handshake.
Configuration details differ between libraries, but the idea stays identical. Queries and mutations use HTTP, while subscriptions use WebSockets.
Because of this separation, the react graphql subscriptions example remains efficient under load.
Configuring the React Client with Apollo
On the React side, a combination of HTTP and WebSocket links is required. Apollo Client offers a straightforward way to compose these links.
The client uses HTTP for standard operations and switches to WebSocket whenever a subscription starts. This logic stays hidden inside the transport layer.
Below is a high-level setup that often appears in a react graphql subscriptions example:
import { ApolloClient, InMemoryCache, split } from '@apollo/client';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
import { createClient } from 'graphql-ws';
import { HttpLink } from '@apollo/client/link/http';
import { getMainDefinition } from '@apollo/client/utilities';
const httpLink = new HttpLink({
uri: 'https://api.example.com/graphql'
});
const wsLink = new GraphQLWsLink(createClient({
url: 'wss://api.example.com/graphql'
}));
const splitLink = split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink
);
export const client = new ApolloClient({
link: splitLink,
cache: new InMemoryCache()
});
This configuration allows one React app to handle queries, mutations, and subscriptions transparently.
React Components for Real-Time Chat and Feed
With Apollo configured, building UI components becomes straightforward. React hooks like useQuery, useMutation, and useSubscription handle data flow.
For a chat view, a list component subscribes to new messages while also loading initial history. A form component sends new messages through a mutation.
Below is a minimal chat UI based on the react graphql subscriptions example:
import { gql, useQuery, useMutation, useSubscription } from '@apollo/client';
const MESSAGES_QUERY = gql`
query Messages {
messages {
id
text
author
createdAt
}
}
`;
const MESSAGE_ADDED_SUBSCRIPTION = gql`
subscription OnMessageAdded {
messageAdded {
id
text
author
createdAt
}
}
`;
const SEND_MESSAGE_MUTATION = gql`
mutation SendMessage($text: String!, $author: String!) {
sendMessage(text: $text, author: $author) {
id
text
author
createdAt
}
}
`;
function Chat() {
const { data, loading } = useQuery(MESSAGES_QUERY);
const { data: subData } = useSubscription(MESSAGE_ADDED_SUBSCRIPTION);
const [sendMessage] = useMutation(SEND_MESSAGE_MUTATION);
const messages = [...(data?.messages || [])];
if (subData?.messageAdded) {
messages.push(subData.messageAdded);
}
// Render messages and form here
}
A live feed component follows the same structure. Only the types and subscription fields differ, not the strategy.
Read More: How to use GraphQL subscriptions in Apollo Client React applications
Handling Edge Cases and Performance
Real-time systems must address several subtle issues. Without careful handling, the user experience can degrade quickly.
Connection loss is a key concern. The WebSocket client should reconnect automatically when the network blips. Many libraries include built-in retry strategies.
On the other hand, large rooms or busy feeds can overwhelm slow devices. A thoughtful react graphql subscriptions example limits the number of items kept in memory.
Pagination and windowing techniques help here. The UI shows the latest items while older ones remain available through explicit queries.
Security matters as well. Authentication tokens must be passed during the WebSocket handshake so the server can authorize each subscription.
Adapting the Pattern to Your Own Projects
The same approach fits many use cases beyond chat. Live dashboards, sports scores, notifications, stock tickers, and collaborative editing all share similar patterns.
Teams can start from a proven react graphql subscriptions example and then layer custom business logic on top. This reduces ramp-up time and avoids common pitfalls.
As a result, React developers can deliver rich real-time experiences without leaving the GraphQL ecosystem. The consistent query language makes onboarding smoother for the whole team.
For reference inside your own codebase, you can even keep a link like react graphql subscriptions example in project documentation to guide new contributors.
When implemented carefully, a robust react graphql subscriptions example becomes the foundation for responsive features that users trust and enjoy. With a clean schema, solid backend, and focused React components, your real-time chat or live feed will feel fast, stable, and ready for production.
