Skip to content

useSubscription Stuck on Loading even though data is sent from server #6578

@lsnow99

Description

@lsnow99

Intended outcome:

  • Have a React Native view with a useSubscription hook.
  • Start it with a certain variable in the where clause of the query.
  • Print any subscription data to the console.
  • Close the view.
  • Re-open the same view.
  • This time start the useSubscription hook with a different variable supplied to the query
  • Print any subscription data to the console

Actual outcome:

  • Have a React Native view with a useSubscription hook.
  • Start it with a certain variable in the where clause of the query.
  • Print any subscription data to the console.
  • Close the view.
  • Re-open the same view.
  • This time start the useSubscription hook with a different variable supplied to the query
  • No data is received by the subscription/output to the console

I have Wireshark capturing traffic and can confirm everything seems to work as expected as far as the network is concerned, making me suspect the client/hook is having an issue:

Open the View for the first time:

  • connection_init message sent to server.
  • Server responds with connection_ack.
  • Client sends start message to the server with the subscription query as payload.
  • Server responds with data message with a payload of the initial results from the query. Here the client is printing the data
    Close the View:
  • Client sends stop message to server.
    Open the View for the second time:
  • start message sent to server.
  • Server responds with a data message with the data as payload Here the client is not printing anything

How to reproduce the issue:
Here's my code:
creating client:

const asyncAuthLink = setContext(async () => {
  const {token} = await auth().currentUser.getIdTokenResult();
  console.log(token);
  return {
    headers: {
      authorization: `Bearer ${token}`,
    },
  };
});

const httpLink = new HttpLink({
  uri: 'http://192.168.1.10:8080/api/v1/graphql',
  credentials: 'same-origin',
});

const wsLink = new WebSocketLink(new SubscriptionClient(
  `ws://192.168.1.10:8080/api/v1/graphql`, {
    reconnect: true,
    lazy: true,
    connectionParams: async() => {
      const {token} = await auth().currentUser.getIdTokenResult();
      return {
        Authorization: `Bearer ${token}`
      }
    }
  }
));

const link = split(
  // split based on operation type
  ({ query }) => {
    const definition = getMainDefinition(query);
    return (
      definition.kind === 'OperationDefinition' &&
      definition.operation === 'subscription'
    );
  },
  wsLink,
  asyncAuthLink.concat(httpLink),
);

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

The View that uses the useSubscription hook:

import React, {useEffect} from 'react';
import {
  View,
  SafeAreaView,
  Text,
} from 'react-native';


import IonIcon from 'react-native-vector-icons/Ionicons';
IonIcon.loadFont();

import { useSubscription } from '@apollo/client';
import API from '../../util/API';
import Queries from '../../util/Queries';

export default function SimpleCallScreen({route}) {
  const [callID, setCallID] = React.useState(-1)

  const {data, loading, error} = useSubscription(Queries.GET_CALL_DATA, {
    variables: {
      call_id: callID,
    },
    skip: callID == -1,
    onSubscriptionData: (da) => {
      // console.log(da)
    },
    fetchPolicy: "network-only"
  });

  if(loading) {
    console.log('loading')
  } else {
    console.log('not loading')
  }
  if(error) {
    console.log(error)
  } else {
    console.log(' no error')
  }
  if(data) {
    console.log(data)
  } else {
    console.log(' no data')
  }

  console.log(data + ' ' + loading + ' ' + error)

  const ringFriend = sdp => {
    API.beginDuoCall({friendship_id: route.params.friendship.id, sdp: sdp})
      .then(re => {
        console.log(`got call id ${re.data.call_id}`)
        setCallID(re.data.call_id)
      })
      .catch(err => {
        console.log(err);
      });
  };
  useEffect(() => {
      ringFriend('nonsense')
  }, []);

  return (
    <SafeAreaView>
      <View>
          <Text>Hi</Text>
          <Text>{loading}</Text>
      </View>
    </SafeAreaView>
  );
}

Here is the console output:

[Sat Jul 11 2020 17:06:34.242]  LOG      not loading
[Sat Jul 11 2020 17:06:34.243]  LOG       no error
[Sat Jul 11 2020 17:06:34.243]  LOG       no data
[Sat Jul 11 2020 17:06:34.246]  LOG      undefined false undefined
[Sat Jul 11 2020 17:06:34.712]  LOG      got call id 292
[Sat Jul 11 2020 17:06:34.739]  LOG      loading
[Sat Jul 11 2020 17:06:34.749]  LOG       no error
[Sat Jul 11 2020 17:06:34.750]  LOG       no data
[Sat Jul 11 2020 17:06:34.753]  LOG      undefined true undefined
[Sat Jul 11 2020 17:06:36.985]  LOG      not loading
[Sat Jul 11 2020 17:06:37.410]  LOG       no error
[Sat Jul 11 2020 17:06:37.410]  LOG      {"call": {"__typename": "calls", "call_memberships": [[Object], [Object]], "id": 292}}
[Sat Jul 11 2020 17:06:37.510]  LOG      [object Object] false undefined
[Sat Jul 11 2020 17:06:49.161]  LOG      not loading
[Sat Jul 11 2020 17:06:49.164]  LOG       no error
[Sat Jul 11 2020 17:06:49.164]  LOG       no data
[Sat Jul 11 2020 17:06:49.164]  LOG      undefined false undefined
[Sat Jul 11 2020 17:06:49.664]  LOG      got call id 293
[Sat Jul 11 2020 17:06:49.666]  LOG      loading
[Sat Jul 11 2020 17:06:49.677]  LOG       no error
[Sat Jul 11 2020 17:06:49.677]  LOG       no data
[Sat Jul 11 2020 17:06:49.677]  LOG      undefined true undefined

^ Here I would expect loading to switch to false and the data to be printed, like the initial call

Versions

  System:
    OS: Linux 5.6 Manjaro Linux
  Binaries:
    Node: 14.3.0 - /usr/bin/node
    Yarn: 1.22.4 - /usr/bin/yarn
    npm: 6.14.5 - /usr/bin/npm
  Browsers:
    Firefox: 78.0.2
  npmPackages:
    @apollo/client: ^3.0.0-rc.12 => 3.0.0-rc.12 
    @apollo/link-context: ^2.0.0-beta.3 => 2.0.0-beta.3 
    @apollo/react-hooks: ^3.1.5 => 3.1.5 
    apollo-boost: ^0.4.9 => 0.4.9 
    apollo-cache-inmemory: ^1.6.6 => 1.6.6 
    apollo-client: ^2.6.10 => 2.6.10 
    apollo-link: ^1.2.14 => 1.2.14 
    apollo-link-error: ^1.1.13 => 1.1.13 
    apollo-link-http: ^1.5.17 => 1.5.17 
    apollo-link-ws: ^1.0.20 => 1.0.20 

I have tested with @apollo/client@3.0.0-beta.45 and @apollo/client@3.0.0-rc.12 and on both iOS and Android

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions