Search code examples
apolloreact-apolloapollo-client

Apollo client writeQuery updates stores, but UI componens only updates after the second function call


"apollo-cache-inmemory": "^1.6.2",
"apollo-client": "^2.6.3",

I setup a simple subscription with the client.subscribe method and try to update the store with the client.writeQuery method

export default class App extends Component<Props> {
  componentDidMount() {
    this.purchaseSubscription = client.subscribe({
      query: PURCHASE_ASSIGNED_SUBSCRIPTION,
      variables: { status: ['INPREPARATION', 'PROCESSED', 'READYFORCOLLECTION', 'ONTHEWAY', 'ATLOCATION'] },
    }).subscribe({
      next: (subscriptionData) => {
        const { cache } = client;
        const prev = cache.readQuery({
          query: MY_PURCHASES,
          variables: { status: ['INPREPARATION', 'PROCESSED', 'READYFORCOLLECTION', 'ONTHEWAY', 'ATLOCATION'] },
         });
        const newPurchase = subscriptionData.data.purchaseAssignedToMe;
        const data = { myPurchases: [...prev.myPurchases, newPurchase] };

        cache.writeQuery({
          query: MY_PURCHASES,
          variables: { status: ['INPREPARATION', 'PROCESSED', 'READYFORCOLLECTION', 'ONTHEWAY', 'ATLOCATION'] },
          data,
        });
      },
      error: (err) => { console.error('err', err) },
    });
  }

  render() {
    return (
      <ApolloProvider client={client}>
        <AppContainer />
      </ApolloProvider>
    );
  }
}

The store gets updated after the call, however the UI component is only re-rendered only on the second publish event.

The UI components is setup the following way:

  <Query
    query={MY_PURCHASES}
    variables={{ status: ['INPREPARATION', 'PROCESSED', 'READYFORCOLLECTION', 'ONTHEWAY', 'ATLOCATION'] }}
    >
   ...
  <Query />

By reading the cache after the writeQuery is called I was able to validate that the store reflect the proper state, however the UI component only gets updated at every second call.

What am I missing here?


Solution

  • ApolloClient.subscribe's next function is very similar to how updateQueries works in Apollo Client’s mutate function, but with the exception that cache.writeQuery does not broadcast the changes if it is not called from the the Mutation's update function.

    SOLUTION: use client.writeQuery(...) instead of cache.writeQuery(...)

    Note: The update function receives cache rather than client as its first parameter. This cache is typically an instance of InMemoryCache, as supplied to the ApolloClient constructor when the client was created. In case of the update function, when you call cache.writeQuery, the update internally calls broadcastQueries, so queries listening to the changes will update. However, this behavior of broadcasting changes after cache.writeQuery happens only with the update function. Anywhere else, cache.writeQuery would just write to the cache, and the changes would not be immediately broadcast to the view layer. To avoid this confusion, prefer client.writeQuery when writing to cache.

    Source: https://www.apollographql.com/docs/react/essentials/mutations/#updating-the-cache