Apollo-client: Invoking a mutation will clear a query's data if the mutation's response isn't a superset of the query's fields

Created on 30 Nov 2018  路  4Comments  路  Source: apollographql/apollo-client

If you do this:

  1. You have a query prop that requests data that contains properties on an optional object, where that object is initially null.
  2. You invoke a mutation that populates creates the optional object but doesn't request all the fields the query requires

Then:

Actual outcome:
The query prop will not contain any data, there will be no errors, and loading is false.

Expected outcome:
The query prop should should throw an error or should refetch the missing data.

How to reproduce the issue:
I've made an error template that reproduces the issue here: https://github.com/kevinmook/react-apollo-error-template

To reproduce, load up the template. The page should show the contents of the query (loading, error, and the data). If you click "Breaks data" it will invoke the "bad" mutation which will clear out the data in the query prop. If you click "Works fine (and fixes data, if broken)" it will invoke the exact same mutation, except it will request all the data specified in the query. This will update the query prop with the new data (and restore it to a non-broken state, if you had clicked "Breaks data").

Versions

  System:
    OS: macOS 10.14.1
  Binaries:
    Node: 8.9.0 - ~/.nvm/versions/node/v8.9.0/bin/node
    Yarn: 1.7.0 - /usr/local/bin/yarn
    npm: 6.4.1 - ~/.nvm/versions/node/v8.9.0/bin/npm
  Browsers:
    Chrome: 70.0.3538.110
    Firefox: 42.0
    Safari: 12.0.1
  npmPackages:
    apollo-cache-inmemory: ^1.2.2 => 1.2.2
    apollo-client: ^2.3.2 => 2.3.2
    apollo-link: ^1.2.2 => 1.2.2
    react-apollo: 2.1.4 => 2.1.4

Most helpful comment

@kevinmook

The apollo-client QueryManager intentionally returns {} and partial: true in this case, to signal a cache miss.

In more recent react-apollo there is a query option called partialRefetch that detects this and refetches if set to true (default is false). There is more information about this in the Changelog-entry for that option at https://github.com/apollographql/react-apollo/blame/master/Changelog.md#L422-L435

See https://github.com/jimmybergman/react-apollo-error-template for a version of your error template that verifies that the option makes the problem go away (by refetching). As explained in the changelog entry you can also reconcile the cache manually using the mutations update prop if refetching is not an option.

All 4 comments

Upon further investigation, it looks like this is a bug in react-apollo. apollo-client is correctly throwing an error, but it's being swallowed by react-apollo.

Edit: never mind, apollo-cache-inmemory (where the problem is) is in this repo

My colleagues were able to track down where the error is being suppressed to here: https://github.com/apollographql/apollo-client/blob/908ba3662cdc59f772f8d9ba5039f182093d019f/packages/apollo-client/src/core/QueryManager.ts#L998-L1000

I think ideally the error not be caught, allowing clients to detect and handle this situation. The way things are it's incredibly difficult to debug what's going on.

@kevinmook

The apollo-client QueryManager intentionally returns {} and partial: true in this case, to signal a cache miss.

In more recent react-apollo there is a query option called partialRefetch that detects this and refetches if set to true (default is false). There is more information about this in the Changelog-entry for that option at https://github.com/apollographql/react-apollo/blame/master/Changelog.md#L422-L435

See https://github.com/jimmybergman/react-apollo-error-template for a version of your error template that verifies that the option makes the problem go away (by refetching). As explained in the changelog entry you can also reconcile the cache manually using the mutations update prop if refetching is not an option.

@jimmybergman that worked! Thank you very much for taking the time to explain and update the error template with the fix!

Was this page helpful?
0 / 5 - 0 ratings