Howtographql: react-apollo/8-subscriptions: why doesn't `_subscribeToNewVotes` need `updateQuery`?

Created on 22 Mar 2018  Â·  7Comments  Â·  Source: howtographql/howtographql

In the first example of subscriptions in Realtime Updates with GraphQL Subscriptions, _subscribeToNewLinks is able listen to live updates and change records in the local cache because of a updateQuery argument to this.props.feedQuery.subscribeToMore

_subscribeToNewLinks = () => {
  this.props.feedQuery.subscribeToMore({
    document: gql`
      subscription {
        // newLink query
      }
    `,
    updateQuery: (previous, { subscriptionData }) => {
      // update the previous state with the new link and return the new state
    }
  });
};

However in the second example, _subscribeToNewVotes, this argument is left off _and it still works_:

_subscribeToNewVotes = () => {
  this.props.feedQuery.subscribeToMore({
    document: gql`
      subscription {
        // newVote query
      }
    `
  });
};

I think this might have to do with Apollo's magical caching? It's able to know what record is being returned and updates it in the local cache with its default dataIdFromObject? But then why did we need it in the first example?

In any case, it'd be super neat to have a sentence or two acknowledging that this is magical and explaining how it's working.

All 7 comments

Apollo can match up vote objects with link objects, so when new votes arrive through the subscription, and some of those votes relate to links being rendered by React, when Apollo modifies the underlying link object to include new votes, React notices that it needs to re-render that object and everything looks right. That's the magic you're talking about.

That magic doesn't apply to newly created links, because they're not part of the root query that's used to select links which are being rendered by React. A new link arrives, but it's not part of the data you're working from, so neither state nor props related to what's onscreen change and no re-render is performed.

The updateQuery handler does exactly what it says on the tin… it updates the root query, adding in a new link. Since that changes the list of links that React is rendering, a re-render is triggered and the new link shows up onscreen.

If this were going to magically happen on its own, Apollo would have to accept new data into its cache and then re-run every query it knows about against all of its cached data, looking for new cached items that match each query's criteria. That'd be less like magical and more like mind-numbingly inefficient.

Thanks @christiangenco for opening this issue 😄 It should be fixed. Closing this!

This is still not clear on that page. It just says Apollo will update votes automatically and doesn't state why the same doesn't apply to updating the link query.

In addition why does only my vote on a link requires updating the cache while other users' vote can automatically updated via subscription?

There seems to be some idiosyncrasies with subscriptions, cache and when Apollo will( or won't) handle updates. I wasn't able to get a clear understanding, may be it was mentioned in earlier chapters but I couldn't find. Some conceptual discussion before diving into the working hackernews example would be helpful similar to the illustration by Evans Hauser in that same page.

Your vote doesn't require updating the cache. It's perfectly fine to do nothing on-screen when you click the arrow to vote, wait for Apollo to send a POST request to the server, let the server process that request, and eventually send a message through the WebSocket connection to update Apollo's cache, wait for React to notice that a prop has changed, and finally re-render that Link component with the updated number of votes.

It's just very unresponsive. Instead, we update the cache directly and assume that it works later on the server as well.

The same is being done with newly created links, now that I look at it closer. Updating the cache is basically an optional step that makes the app seem more responsive.

The updateQuery method in _subscribeToNewLinks seems to be there to retain the Link we added if we created it ourselves, possibly to keep the vote-counts from being off if we created it and voted for it before being notified via the subscription that it was created. At least, I think that was the author's intent. This may be unnecessary, and this is just showcasing how to do something like this if your use-case requires it?

Not sure how one would go about updating the tutorial to explain the ins and outs and whys of all of this though. Maybe this issue should be re-opened?

@broberson Your comment on responsiveness as reason to update cache rather than wait for the subscription round trip makes much sense! Still would help stating this explicitly for someone who is just starting out with apollo graphql.

And if updateQuery was not provided in _subscribeToNewLinks, then Apollo would automagically update the data.feed.links array used to render the links just like _subscibeToNewVotes barring any UI responsiveness issues? Is Apollo using the shape of the subscription to determine what exactly inside data.feed needs to be updated? A few words on this would greatly clear the confusion.

Re-opening the issue would help, however if there is a different rationale why not then I'd like to know.

Was this page helpful?
0 / 5 - 0 ratings