Skip to content

[v4] GraphQL cache issue because of API schema formatΒ #12180

@M1CK431

Description

@M1CK431

Bug report

Describe the bug

Because of id and attributes split in API schema the GraphQL cache can't be updated and raise a warning in the browser console (among obvious cache handling issue).

The warning message from the console is:

invariant.ts?6cf4:42 Cache data may be lost when replacing the attributes field of a ExampleEntity object.

To address this problem (which is not a bug in Apollo Client), either ensure all objects of type Example have an ID or a custom merge function, or define a custom merge function for the ExampleEntity.attributes field, so InMemoryCache can safely merge these objects:

  existing: {"__typename":"Example","createdAt":"2021-12-25T23:43:56.648Z","firstName":"John","lastName":"Do","message":"I'm asleep","status":"NEW","dueDate":null,"referer":"https://example.com","contactDetails":[],"user":{"__typename":"UsersPermissionsUserEntityResponse","data":null}}
  incoming: {"__typename":"Example","dueDate":null,"firstName":"John","lastName":"Do","message":"I'm asleep","referer":"https://example.com","ipAddress":"12.34.56.78","createdAt":"2021-12-25T23:43:56.648Z","updatedAt":"2021-12-25T23:43:56.648Z","contactDetails":[],"communications":[]}

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

This is because the GraphQL schema is the following:

  • example query:
example(id: ID): ExampleEntityResponse
type ExampleEntityResponse {
  data: ExampleEntity
}
id: ID

and

data: ExampleEntity
type ExampleEntity {
  id: ID
  attributes: Example
}

Steps to reproduce the behavior

  1. Using GraphQL API, request the same asset in a query and in the result of a mutation (for example)
  2. See warning message in the browser console

Expected behavior

The id and attributes split in the GraphQL API schema is incomprehensible for me. I can't understand why there are not in the same object (like Apollo Client is obviously expecting to find it). In addition, I also can't understand why we need to wrap everything in a data object while fetching a single asset. I guess there is strong reasons for such things, but I can't actually believe them 🀯

IMHO, the expected schema should be like this:

example(id: ID!): Example
type Example {
  id: ID!
  createdAt: DateTime!
  updatedAt: DateTime!
  // other fields...
}

Screenshots

N/A

Code snippets

Regardless the GraphQL cache issue, I'm currently forced to write such code in every query/mutation (and I really hate it 😠):

function Example({ id, attributes }) {
  Object.assign(this, { id, ...attributes });
}

this.$apollo
  .query({ query: examplesQuery, variables: { ids: this.ids } })
  .then(({ data: { examples: { data } } }) => {
    const examples = data.map(e => new Example(e));
    // finally some useful code
  }

Strapi v3 use by far more "dev friendly" in this respect (no useless data wrapper for single asset, no incomprehensible id and attributes split).

System

  • Node.js version: v16.13.1
  • NPM version: v8.1.2
  • Strapi version: v4.0.5
  • Database: MariaDB
  • Operating system: Archlinux

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions