Ad

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:

enter image description here

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.

oc

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?

Ad

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

Ad
source: stackoverflow.com
Ad