Apollo Subscriptions: Apollo Graphql Is Receiving Updates On Playground But Not On Client
I'm using react on Apollo GraphQL subscriptions and I can receive updates on Apollo Playground but not on Client. Here is the response on the Apollo Playground:
Graphql Server is on http://localhost:4000/
and subscriptions on ws://localhost:4000/graphql. However, it works on the playground but not on client-side. I have set up Apollo client in this manner to receive updates from server:
import ApolloClient from 'apollo-boost';
import { WebSocketLink } from 'apollo-link-ws';
import { HttpLink } from 'apollo-link-http';
import { split } from 'apollo-link';
import { getMainDefinition } from 'apollo-utilities';
const httpLink = new HttpLink({
uri: 'http://localhost:4000/graphql'
});
export const wsLink = new WebSocketLink({
uri: `ws://localhost:4000/graphql`,
options: {
reconnect: false
}
});
export const link = split(
// split based on operation type
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink,
);
export const client = new ApolloClient({
uri: 'http://localhost:4000/',
});
In my view I have used useSubscriptions
:
const MESSAGE_SENT_SUBSCRIPTION = gql`subscription {
messageSent {
id
message
}
}`
const {data: newMessage, loading: newMessageLoading} = useSubscription(MESSAGE_SENT_SUBSCRIPTION, {});
And on render, I have used:
{!newMessageLoading && JSON.stringify(newMessage)}
But from client, it doesn't receive updates but I am sure that it connects with Graphql WebSockets server.
Server Side:
let database = require("./src/database.js")
let schema = require("./src/schema.js");
let resolvers = require("./src/resolvers.js");
let {ApolloServer} = require("apollo-server");
// The ApolloServer constructor requires two parameters: your schema
// definition and your set of resolvers.
const server = new ApolloServer({
typeDefs: schema,
resolvers: resolvers,
context: {
database
}
});
// The `listen` method launches a web server.
server.listen().then(({ url,subscriptionsUrl ,subscriptionsPath}) => {
console.log(`🚀 Server ready at ${url}`);
console.log(`realtime here at ${subscriptionsUrl} and path ${subscriptionsPath}`)
});
What I'm doing wrong here, Is there anyone who came across with such issue?
Answer
You need to pass splited link to ApolloClient constructor. Try to pass it like this (client side):
import ApolloClient from 'apollo-boost';
import { WebSocketLink } from 'apollo-link-ws';
import { HttpLink } from 'apollo-link-http';
import { split } from 'apollo-link';
import { onError } from 'apollo-link-error';
import { getMainDefinition } from 'apollo-utilities';
const httpLink = new HttpLink({
uri: 'http://localhost:4000/graphql'
});
export const wsLink = new WebSocketLink({
uri: `ws://localhost:4000/subscriptions`,
options: {
reconnect: false
}
});
export const link = split(
// split based on operation type
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink,
);
export const graphqlServer = new ApolloClient({
link: ApolloLink.from([
onError(({
graphQLErrors,
networkError
}) => {
if (graphQLErrors) {
graphQLErrors.map(({
message,
locations,
path
}) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
);
}
if (networkError) {
console.log(`[Network error]: ${networkError}`);
}
}),
link // YOUR LINK (NOW MATCHING YOUR CODE)
])
});
And server side:
...
const server = new ApolloServer({
typeDefs: schema,
resolvers: resolvers,
subscriptions: {
path: '/subscriptions'
},
context: {
database
}
});
...
Note that /subscriptions
also passed to ApolloClient
Related Questions
- → Import statement and Babel
- → should I choose reactjs+f7 or f7+vue.js?
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → .tsx webpack compile fails: Unexpected token <
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → React Native with visual studio 2015 IDE
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM
- → How do I determine if a new ReactJS session and/or Browser session has started?
- → Alt @decorators in React-Native
- → How to dynamically add class to parent div of focused input field?