Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apollo subscriptions - Nextjs - Error: Observable cancelled prematurely at Concast.removeObserver

I am trying to use apollo/graphql subscription in my nextjs project, my graphql server is placed in external nextjs service,I can work with queries and mutation without any problem but when I use an implementation of useSubscription I get the following error:

"Error: Observable cancelled prematurely at Concast.removeObserver (webpack-internal:///../../node_modules/@apollo/client/utilities/observables/Concast.js:118:33) at eval (webpack-internal:///../../node_modules/@apollo/client/utilities/observables/Concast.js:21:47) at cleanupSubscription (webpack-internal:///../../node_modules/zen-observable-ts/module.js:92:7) at Subscription.unsubscribe (webpack-internal:///../../node_modules/zen-observable-ts/module.js:207:7) at cleanupSubscription (webpack-internal:///../../node_modules/zen-observable-ts/module.js:97:21) at Subscription.unsubscribe (webpack-internal:///../../node_modules/zen-observable-ts/module.js:207:7) at eval (webpack-internal:///../../node_modules/@apollo/client/react/hooks/useSubscription.js:106:26) at safelyCallDestroy (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:22763:5) at commitHookEffectListUnmount (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:22927:11) at invokePassiveEffectUnmountInDEV (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:24998:13) at invokeEffectsInDev (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:27137:11) at commitDoubleInvokeEffectsInDEV (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:27110:7) at flushPassiveEffectsImpl (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:26860:5) at flushPassiveEffects (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:26796:14) at eval (webpack-internal:///../../node_modules/react-dom/cjs/react-dom.development.js:26592:9) at workLoop (webpack-internal:///../../node_modules/scheduler/cjs/scheduler.development.js:266:34) at flushWork (webpack-internal:///../../node_modules/scheduler/cjs/scheduler.development.js:239:14) at MessagePort.performWorkUntilDeadline (webpack-internal:///../../node_modules/scheduler/cjs/scheduler.development.js:533:21)"

I know that the subscriptions server is working right because I can to listening from apollo studio and I have created a spa with create-react-app and it works fine

I have used:

Server:

  • "apollo-server-express": "^3.6.7"
  • "graphql-ws": "^5.7.0"

Client

  • "next": "^12.1.5"
  • "@apollo/client": "^3.5.10"
  • "graphql-ws": "^5.7.0"

Hook implementation

const room = useSubscription(
    gql`
      subscription onRoomAdded($roomAddedId: ID!) {
        roomAdded(id: $roomAddedId) {
          id
          name
        }
      }
    `
  );

Client implementation

import { ApolloClient, HttpLink, InMemoryCache, split } from '@apollo/client';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
import { getMainDefinition } from '@apollo/client/utilities';
import { createClient } from 'graphql-ws';
import fetch from 'isomorphic-fetch';

const HOST = 'http://localhost:3001/graphql';
const HOST_WS = 'ws://localhost:3001/graphql';
const isServer = typeof window === 'undefined';

if (isServer) {
  global.fetch = fetch;
}

const httpLink = new HttpLink({
  uri: HOST,
});

const link = isServer
  ? httpLink
  : split(
      ({ query }) => {
        const definition = getMainDefinition(query);
        return (
          definition.kind === 'OperationDefinition' &&
          definition.operation === 'subscription'
        );
      },
      new GraphQLWsLink(
        createClient({
          url: HOST_WS,
        })
      ),
      httpLink
    );

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

export default client;

any idea about the problem? I think the problem could be that NextJS only works with subscriptions-transport-ws but in the official apollo documentation indicates that the new official way is to use graphql-ws the other library is unmaintained already

UPDATE! I have checked that the subscriptions are working right in production build, I'm investigating how to implement in development process. any suggestions are welcome.

like image 716
rrios Avatar asked Sep 15 '25 22:09

rrios


1 Answers

If it is working in production, but in not in dev, you may have the same issue I had with my React SPA: StrictMode and double rendering as described in this github issue. So far I have found 2 ways to make it work:

  1. remove StrictMode
  2. subscribe with vanilla JS instead ofuseSubscription
const ON_USER_ADDED = gql`
  subscription OnUserAdded {
    userAdded {
      name
      id
    }
  }
`;

const subscribe = () => {
client.subscribe({
  query: ON_USER_ADDED,
}).subscribe({
    next(data) {
      console.log('data', data);
    },
    complete(){
      console.log('complete');
    },
    error(err) {
      console.log('error', err);
    }
  })
};
like image 120
Sipann Avatar answered Sep 19 '25 20:09

Sipann