Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

null ID should not be considered cacheable keys #9814

Closed
mschipperheyn opened this issue Jun 12, 2022 · 5 comments · Fixed by #9862
Closed

null ID should not be considered cacheable keys #9814

mschipperheyn opened this issue Jun 12, 2022 · 5 comments · Fixed by #9862
Assignees

Comments

@mschipperheyn
Copy link

Intended outcome:
I have a server side response that contains an array with two different objects with null IDs. I would expect that the missing cache key would not be interpreted as an actual cache key and I would get 2 different objects on the client side.

Actual outcome:
What I'm getting is an array with 2 identical objects. A missing cache key should be considered as a "unique value".

How to reproduce the issue:
Graphql

type Product {
	id: ID!
	label: String!
	sku: String!
	productType: ProductType!
	costCategory: CostCategory!
	assetRangeFrom: Float
	assetRangeTo: Float
	state: State
	city: String
	year: Int
	costType: CostType!
	price: Float
	pricePercentage: Float
	costFloor: Float
	costCeiling: Float
	costExemption: Float
	charge: Boolean!
	createdAt: DateTime!
	updatedAt: DateTime!
}
type OrderLine {
	id: ID
	quantity: Int!
	product: Product!
	percentageValueBase: Float
	createdAt: DateTime
	updatedAt: DateTime
}

server side query results (Note the different id)

[
  {
    productId: '42df9f30-db9e-11ec-aaef-f158a82a932b',
    product: Product {
      dataValues: [Object],
      _previousDataValues: [Object],
      uniqno: 1,
      _changed: [Set],
      _options: [Object],
      isNewRecord: false,
      cache: [Function: cache],
      id: [Getter/Setter],
      searchText: [Getter/Setter],
      label: [Getter/Setter],
      sku: [Getter/Setter],
      productType: [Getter/Setter],
      costCategory: [Getter/Setter],
      costType: [Getter/Setter],
      state: [Getter/Setter],
      year: [Getter/Setter],
      assetRangeFrom: [Getter/Setter],
      assetRangeTo: [Getter/Setter],
      price: [Getter/Setter],
      pricePercentage: [Getter/Setter],
      costFloor: [Getter/Setter],
      costCeiling: [Getter/Setter],
      costExemption: [Getter/Setter],
      charge: [Getter/Setter],
      primaryKeyAttributes: [Array]
    },
    quantity: 1,
    percentageValueBase: 10000
  },
  {
    productId: 'd68daa10-daef-11ec-bfb6-55f481ef4749',
    product: Product {
      dataValues: [Object],
      _previousDataValues: [Object],
      uniqno: 1,
      _changed: [Set],
      _options: [Object],
      isNewRecord: false,
      cache: [Function: cache],
      id: [Getter/Setter],
      searchText: [Getter/Setter],
      label: [Getter/Setter],
      sku: [Getter/Setter],
      productType: [Getter/Setter],
      costCategory: [Getter/Setter],
      costType: [Getter/Setter],
      state: [Getter/Setter],
      year: [Getter/Setter],
      assetRangeFrom: [Getter/Setter],
      assetRangeTo: [Getter/Setter],
      price: [Getter/Setter],
      pricePercentage: [Getter/Setter],
      costFloor: [Getter/Setter],
      costCeiling: [Getter/Setter],
      costExemption: [Getter/Setter],
      charge: [Getter/Setter],
      primaryKeyAttributes: [Array]
    },
    quantity: 1,
    percentageValueBase: null
  }
]

client side query result (note the identical ID)

[
  {
    __typename: 'OrderLine',
    id: null,
    quantity: 1,
    percentageValueBase: 10000,
    product: {
      __typename: 'Product',
      id: '42df9f30-db9e-11ec-aaef-f158a82a932b',
      label: 'Taxa de serviço advogado',
      sku: 'ASSETFEE_2022_SP',
      productType: 'ASSET',
      costCategory: 'LAWYER',
      assetRangeFrom: null,
      assetRangeTo: null,
      state: 'SP',
      city: null,
      year: 2022,
      costType: 'PERCENTAGE',
      price: null,
      pricePercentage: 0.09,
      costExemption: 0,
      costFloor: 965,
      costCeiling: null,
      charge: false,
      updatedAt: '2022-05-24T20:15:31.000Z',
      createdAt: '2022-05-24T20:15:31.000Z'
    }
  },
  {
    __typename: 'OrderLine',
    id: null,
    quantity: 1,
    percentageValueBase: 10000,
    product: {
      __typename: 'Product',
      id: '42df9f30-db9e-11ec-aaef-f158a82a932b',
      label: 'Taxa de serviço advogado',
      sku: 'ASSETFEE_2022_SP',
      productType: 'ASSET',
      costCategory: 'LAWYER',
      assetRangeFrom: null,
      assetRangeTo: null,
      state: 'SP',
      city: null,
      year: 2022,
      costType: 'PERCENTAGE',
      price: null,
      pricePercentage: 0.09,
      costExemption: 0,
      costFloor: 965,
      costCeiling: null,
      charge: false,
      updatedAt: '2022-05-24T20:15:31.000Z',
      createdAt: '2022-05-24T20:15:31.000Z'
    }
  }
]

Versions

 System:
    OS: macOS 12.2.1
  Binaries:
    Node: 16.15.0 - ~/.nvm/versions/node/v16.15.0/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 8.5.5 - ~/.nvm/versions/node/v16.15.0/bin/npm
  Browsers:
    Chrome: 102.0.5005.61
    Safari: 15.3
  npmPackages:
    @apollo/client: ^3.6.7 => 3.6.7 
@mschipperheyn mschipperheyn changed the title null ID overwrites record null ID overwrites record (client side cache) Jun 12, 2022
@mschipperheyn
Copy link
Author

I solved this by using a typePolicy referencing the product.id, which in this case is unique for each query result. But I don't think this should be necessary. The default behaviour is counter intuitive and can easily lead to unexpected errors.

@mschipperheyn
Copy link
Author

Another approach would be to exclude the id for let's say non id scenario's. But it all seems a bit of overkill. null ids should simply not be considered cacheable keys

@mschipperheyn mschipperheyn changed the title null ID overwrites record (client side cache) null ID should not be considered cacheable keys Jun 13, 2022
@jpvajda jpvajda added 🔍 investigate Investigate further 🏓 awaiting-team-response requires input from the apollo team labels Jun 17, 2022
@benjamn benjamn self-assigned this Jun 27, 2022
@benjamn
Copy link
Member

benjamn commented Jun 27, 2022

@mschipperheyn Sorry to keep you waiting here, but I fully agree the default behavior should be to treat multiple objects with id: null as unrelated, rather than treating them as the same object.

@benjamn benjamn added 🛫 in-progress 💸 caching and removed 🏓 awaiting-team-response requires input from the apollo team labels Jun 27, 2022
alessbell pushed a commit that referenced this issue Sep 21, 2022
…h ids (#9862)

* Reject id:null and id:undefined in defaultDataIdFromObject.

* Passing regression tests for issue #9814.
@bignimbus
Copy link
Contributor

Hi all 👋🏻 I'm doing some housekeeping and noticed that this issue should have been closed by #9862. So I'm closing the loop and therefore, this issue! Let us know if you need more support here 🙏🏻

@github-actions
Copy link
Contributor

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
For general questions, we recommend using StackOverflow or our discord server.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants