Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

Subscription component loading forever #3424

Open
JaEdmuva opened this issue Aug 28, 2019 · 7 comments
Open

Subscription component loading forever #3424

JaEdmuva opened this issue Aug 28, 2019 · 7 comments

Comments

@JaEdmuva
Copy link

Intended outcome:

Get data from subscription using Subscription component from @apollo/react-components.
Result data should be updated, including loading value.

<Subscription subscription={SUBSCRIPTION} client={client}> {this.myFunction} </Subscription>
Client is created using this:

export const createClient = ({ uri, ws }) => new ApolloClient({ defaultOptions: { watchQuery: { fetchPolicy: 'cache-and-network', }, }, cache, link: ApolloLink.from([ ApolloLogger, 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}`);
}
}),
new RetryLink({ attempts: { max: Infinity } }).split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
new WebSocketLink({
uri: ws,
options: {
reconnect: true,
},
}),
new HttpLink({
uri,
credentials: 'same-origin',
})
),
]),
typeDefs,
resolvers,
});

`
Actual outcome:

Result data does not get updated, even when apollo-link-logger shows the result in the console.
Simple console.log(result) is being used in myFunction to see the callback results. First time it's rendered it logs with loading=true. It never gets called again with loading=false or any other data (no console.log printed).

How to reproduce the issue:

Normally this will happen with subscriptions. Every now and then it works as expected, but most of the time it just does not work.

Version

System:
OS: macOS 10.14.6
Binaries:
Node: 10.16.2 - ~/.nvm/versions/node/v10.16.2/bin/node
Yarn: 1.17.3 - /usr/local/bin/yarn
npm: 6.9.0 - ~/.nvm/versions/node/v10.16.2/bin/npm
Browsers:
Chrome: 76.0.3809.100
Safari: 12.1.2
npmPackages:
apollo-cache-inmemory: ^1.6.3 => 1.6.3
apollo-cache-persist: ^0.1.1 => 0.1.1
apollo-client: ^2.6.4 => 2.6.4
apollo-link: ^1.2.12 => 1.2.12
apollo-link-error: ^1.1.11 => 1.1.11
apollo-link-http: ^1.5.15 => 1.5.15
apollo-link-logger: ^1.2.3 => 1.2.3
apollo-link-rest: ^0.7.3 => 0.7.3
apollo-link-retry: ^2.2.14 => 2.2.14
apollo-link-ws: ^1.0.18 => 1.0.18
apollo-utilities: ^1.3.2 => 1.3.2

@hwillson
Copy link
Member

hwillson commented Sep 6, 2019

Any chance you can provide a small runnable reproduction that shows this happening?

@schettino
Copy link

I was facing this as well. The WS was still receiving all messages just fine, but for some reason the values within the useSubscription hook got staled. My guess is when the server responds too fast (under the 100ms ish) it could make this to happen.

The workaround I did relies on the onSubscriptionData, like below

const [values, setValues] = useState<
    Partial<SubscriptionResult<SubscribeActivePromotion>>
  >({});

  useSubscription<SubscribeActivePromotion, SubscribeActivePromotionVariables>(
    subscribeActivePromotion,
    {
      onSubscriptionData(options) {
        setValues(() => options.subscriptionData);
      },
      variables: {
        partnerId: props.partnerId,
      },
    }
  );

@pkvince
Copy link

pkvince commented Sep 11, 2019

Having the same problem. The workaround @schettino suggested is working for me! :)

@JaEdmuva
Copy link
Author

@hwillson not able to provide a runnable right now since I'm using react native. If it guides you better, it's very likely to reproduce when debug is enabled and dev tools hooked.

@semenovDL
Copy link

I have the same issue. Workaround from @schettino works great with one small addition - don't forget to pass { loading: true } when initializing state.

const useSubscription = <TData, TVariables>(
  query: DocumentNode,
  options?: SubscriptionHookOptions<TData, TVariables>,
) => (variables: TVariables) => {
  const [values, setValues] = useState<Partial<SubscriptionResult<TData>>>({
    loading: true
  });
  __useSubscription<TData, TVariables>(
    query,
    {
      ...options,
      variables,
      onSubscriptionData: (options) => {
        setValues(() => options.subscriptionData);
      }
    }
  );
  return values;
};

@DanielRNDev
Copy link

I have the same issue, subscription keeps loading at first initialize, reload the app it's work without issue.
I try to set lazy in subscription options to true and it's work on my case.

@0xdevalias
Copy link

0xdevalias commented Apr 3, 2020

Probably related: #3802

Root cause:
As identified in the video, I believe the root cause is a race condition in /packages/hooks/src/data/SubscriptionData.ts which implicitly requires that isMounted will be set to true before updateResult is called, and this is not always the case.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants