Apollo-client: "Cache data may be lost when replacing the <whatever> field of a Query object." - custom merge function is never called

Created on 20 Aug 2020  ·  4Comments  ·  Source: apollographql/apollo-client

Intended outcome:
The custom merge function I defined would be called.

Actual outcome:
The custom merge is not called, and the warning persists. The complete warning is:

console.warn
    Cache data may be lost when replacing the project field of a Query object.

    To address this problem (which is not a bug in Apollo Client), define a custom merge function for the Query.project field, so InMemoryCache can safely merge these objects:

      existing: {"id":"666","customerShotSearch({\"input\":{\"id\":\"project-666-all-shots-count\",\"params\":{}}})":{"id":"project-666-all-shots-count","count":123}}
      incoming: {"id":"666","customerShotSearch({\"input\":{\"id\":\"project-666-search-shots-count\",\"params\":{\"likes\":\"false\",\"tag\":\"bills,tacos\",\"term\":\"foobar\"}}})":{"id":"project-666-search-shots-count","count":777}}

    For more information about these options, please refer to the documentation:

      * Ensuring entity objects have IDs: https://go.apollo.dev/c/generating-unique-identifiers
      * Defining custom merge functions: https://go.apollo.dev/c/merging-non-normalized-objects

My custom merge is set up as so:

  const cache = new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          project: {
            merge(existing, incoming) {
              return { ...existing, ...incoming };
            }
          }
        }
      }
    }
  });

We do have a few other custom merges (but not on the root Query object) that work fine. Maybe that is related to why this isn't being called.

How to reproduce the issue:
I'm not sure how to get it reproduced in something small.

Versions
System:
OS: Linux 5.3 Ubuntu 19.10 (Eoan Ermine)
Binaries:
Node: 12.16.3 - ~/.nvm/versions/node/v12.16.3/bin/node
Yarn: 1.22.4 - ~/.yarn/bin/yarn
npm: 6.14.4 - ~/.nvm/versions/node/v12.16.3/bin/npm
Browsers:
Chrome: 83.0.4103.116
Firefox: 78.0.2
npmPackages:
@apollo/client: 3.1.3 => 3.1.3

Most helpful comment

@benjamn why do we have to use it like so? Im using three components, which all grab something from the Basket:0 they need. Now with merging it gets merged into a big single Basket:0, but why isn't this done automatically? It feels weird to query what you need, but then also think about this typePolicies. Because when not done, latest query wins and other two components go into blank :(

All 4 comments

Can you try it with merge: true (introduced in #6714)?

const cache = new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        project: {
          merge: true,
        }
      }
    }
  }
})

It _might_ be important for these objects to have a __typename, though I wouldn't have thought that was necessary. I don't see anything else that could be wrong with the code you've shown, so a reproduction would be helpful to move forward (if possible).

@benjamn I can confirm that merge: true resolves the warning. I'm not sure what the difference is between that and the explicit function def, but my issue is solved. You're correct that I had to add __typename to a couple of mock results as well. Thanks!

I got error
Cannot automatically merge arrays while using @benjamn solution
const cache = new InMemoryCache({ typePolicies: { Query: { fields: { project: { merge: true, } } } } })

This tweak solved it for me

const cache = new InMemoryCache({ typePolicies: { Query: { fields: { project: { merge(existing, incoming){ return incoming } } } } } })

@benjamn why do we have to use it like so? Im using three components, which all grab something from the Basket:0 they need. Now with merging it gets merged into a big single Basket:0, but why isn't this done automatically? It feels weird to query what you need, but then also think about this typePolicies. Because when not done, latest query wins and other two components go into blank :(

Was this page helpful?
0 / 5 - 0 ratings