Could not find "client" in the context or passed in as an option issue when using subscriptions

204 Views Asked by At

I need to fetch some data in real-time. So I decided to use the WebSocket connection

import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloLink, split } from "apollo-link";
import { WebSocketLink } from "apollo-link-ws";
import { HttpLink } from "apollo-link-http";
import { setContext } from "apollo-link-context";
import { firebaseAppAuth } from "../../App";
import { onError } from "apollo-link-error";
import { getMainDefinition } from "apollo-utilities";

import config from "../../config";

const authLink = setContext((_, { headers }) => {
  //it will always get unexpired version of the token
  if (firebaseAppAuth && firebaseAppAuth.currentUser) {
    return firebaseAppAuth.currentUser.getIdToken().then((token) => {
      return {
        headers: {
          ...headers,
          "content-type": "application/json",
          authorization: token ? `Bearer ${token}` : "",
        },
      };
    });
  } else {
    return {
      headers: {
        ...headers,
      },
    };
  }
});

const errLink = onError(({ graphQLErrors, networkError }) => {
  console.log(graphQLErrors);
  console.log(networkError);
  if (graphQLErrors)
    graphQLErrors.forEach(({ message, locations, path }) => {
      console.log(
        `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
      );
    });
  if (networkError) {
    console.log(`[Network error]: ${networkError}`);
  }
});

const httpLink = new HttpLink({
  uri: config.adminAPI,
});

const wsLink = new WebSocketLink({
  uri: config.apiSocket, // use wss for a secure endpoint
  options: {
    reconnect: true,
  },
});

const splittedLink = split(
  // split based on operation type
  ({ query }) => {
    const { kind, operation } = getMainDefinition(query);
    return kind === "OperationDefinition" && operation === "subscription";
  },
  wsLink,
  httpLink
);

const link = ApolloLink.from([errLink, authLink, splittedLink]);

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

export default client;

I created authLink, errLink, httpLink and wsLink like the above code. and used the split function to combine httpLink and wsLink, it can run queries without any issues, but when I try to run a subscription hook, it throws following error message.

Could not find "client" in the context or passed in as an option. Wrap the root component in an <ApolloProvider>, or pass an ApolloClient instance in via options.  

I am also passing the client as a prop

ReactDOM.render(
  <BrowserRouter>
    <ApolloProvider client={client}>
      <SnackbarProvider maxSnack={5}>
        <SnackbarUtilsConfigurator />
        <Route path="/" component={App} />
      </SnackbarProvider>
    </ApolloProvider>
  </BrowserRouter>,
  document.getElementById("root")
);

How to resolve this issue?

1

There are 1 best solutions below

1
On

Could you please share how are you using ApolloProvider? It looks like you are missing this:

import React from 'react';
import { render } from 'react-dom';
import { ApolloProvider } from '@apollo/client/react';

const client = new ApolloClient({ uri, cache });

function App() {
  return (
    <div>
      <h2>My first Apollo app </h2>
    </div>
  );
}

render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById('root'),
);

Make sure that you're passing client as a prop to ApolloProvider