Basically, when there is more than one client connected, only the last client connected receives GraphQL subscriptions data through the web socket.
This doesn't happen with old React classes, it happens only when I use stateless functions through Apollo Hooks Provider. I tried several methods already, such as subscribeToMore
(that was working perfectly with classes) or useSubscription
and in general everything that is suggested on this page https://www.apollographql.com/docs/react/data/subscriptions/.
These are the relevant parts of the component code, the subscribeToMore part is basically copy-pasted from an old React class where it works perfectly on the same project.
(If there are missing functions or variables, it's just because I avoided to post a lot of clutter, the code has been tested and runs with no error except for the subscriptions problem)
import React, { useEffect, useState } from 'react';
import { compose } from 'redux';
// other imports
function CommentsPanel(props) {
const { loading, documentComments: comments } = commentsQuery;
const [subscribed, setSubscribed] = useState(false);
useEffect(() => {
if (loading || comments == null || subscribed) return;
console.log(commentsQuery);
commentsQuery.subscribeToMore({
document: ON_COMMENT_ADDED,
variables: {
documentId: projectId,
userId: Meteor.userId(),
},
updateQuery: (previousResult, { subscriptionData }) => {
console.log('On comment added subscription');
return {
...previousResult,
documentComments: [
subscriptionData.data.commentAdded,
...previousResult.documentComments,
],
};
},
});
// other similar subscriptions
setSubscribed(true);
}, [loading, comments, subscribed, commentsQuery, projectId]);
//render and a bunch of other stuff
export default compose(
graphql(DOCUMENT_COMMENTS, {
name: 'commentsQuery',
options: ({ projectId }) => ({
variables: {
documentId: projectId,
},
}),
}),
withStyles(styles),
)(CommentsPanel);
And this is the client
import React from 'react';
import 'babel-polyfill';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { hydrate } from 'react-dom';
import { BrowserRouter, Switch } from 'react-router-dom';
import { ThemeProvider as MuiThemeProvider } from '@material-ui/core/styles';
import { ApolloProvider } from 'react-apollo';
import { ApolloProvider as ApolloHooksProvider } from '@apollo/react-hooks';
import { Accounts } from 'meteor/accounts-base';
import { Meteor } from 'meteor/meteor';
import { Bert } from 'meteor/themeteorchef:bert';
import CssBaseline from '@material-ui/core/CssBaseline/CssBaseline';
import reducerApp from '../../reducers';
import apolloClient from './apollo';
import App from '../../ui/layouts/App';
import theme from '../theme';
Bert.defaults.style = 'growl-bottom-right';
Accounts.onLogout(() => apolloClient.resetStore());
const store = createStore(reducerApp);
const rootElement = document.getElementById('react-root');
Meteor.startup(() =>
hydrate(
<MuiThemeProvider theme={theme}>
<CssBaseline />
<ApolloProvider client={apolloClient}>
<ApolloHooksProvider client={apolloClient}>
<Provider store={store}>
<BrowserRouter>
<Switch>
<App />
</Switch>
</BrowserRouter>
</Provider>
</ApolloHooksProvider>
</ApolloProvider>
</MuiThemeProvider>,
rootElement,
),
);