Apollo-client: readFragment returns null when data normalization isn't manualy setup

Created on 10 Apr 2018  Â·  3Comments  Â·  Source: apollographql/apollo-client

Intended outcome:

I'm expecting that behavior regarding data normalization in the in-memory-cache to be consistant between readQuery and readFragment.

As I understood, the default behavior if the dataIdFromObject option is not set is : use the id field for the data normalization.

Documentation says:

By default, InMemoryCache will attempt to use the commonly found primary keys of id and _id for the unique identifier if they exist along with __typename on an object.

Actual outcome:

For the same set of data (using an "id" field and returning __typename),

When the dataIdFromObject isn't set : readQuery returns data and readFragment returns null
When the dataIdFromObject is set to o => o.id : readQuery and readFragment return correct data

How to reproduce the issue:

Here is a reproduction of the issue : https://stackblitz.com/edit/angular-graphql-normalization-test?file=app%2Fapp.module.ts

By toggling on and off the dataIdFromObject on the line 31 of app.module.ts, the readFragment response will be correct or null.

The queries are in app.component.ts.

Version

Issue Labels

  • [X] has-reproduction
  • [ ] feature
  • [ ] docs
  • [ ] blocking
  • [ ] good first issue

Most helpful comment

That's because

By default, InMemoryCache will attempt to use the commonly found primary keys of id and _id for the unique identifier if they exist along with __typename on an object. (Source)

Meaning that in your fragment you need to have both the id and the _typename, like so

{ id: "Person:1", ... }

and not

{ id: "1", ... }

All 3 comments

That's because

By default, InMemoryCache will attempt to use the commonly found primary keys of id and _id for the unique identifier if they exist along with __typename on an object. (Source)

Meaning that in your fragment you need to have both the id and the _typename, like so

{ id: "Person:1", ... }

and not

{ id: "1", ... }

Oh I see now. It means that the "id" passed to fragment queries are the "id" used in the cache not the one in the db. By setting dataIdFromObject to o => o.id I was just asking the "id" from the cache to behave just like the one in the database.

My bad, the readFragment's documentation was really clear on that point.

While the "id" of readFragment is cache oriented, this is not the case of the variables (id for instance) passed along to a readQuery which stays the same as original watchQuery : db oriented.

readQuery({
      query: queryAuthor,
      variables: { id: "1" } // <-- db oriented (even if looking only in cache)
    })

…

readFragment({
          id: "Person:1", // <-- cache oriented
          fragment: queryPersonFragment
        })

The reason for that is probably because it's not possible for readFragment to always find out what is the cache key : one can define cache key not just depending on the database id and the typename.

Thanks @alex996 for helping me understand.

Closing since this was explained in https://github.com/apollographql/apollo-client/issues/3296#issuecomment-389575236. Thanks!

Was this page helpful?
0 / 5 - 0 ratings