Subsequent queries can cause previous data to appear "missing" due to normalization
- Dominant language
- Rust
- Stars
- 19k
- Forks
- 1.9k
- PR merge metrics
- No merged PRs in 30d
Description
I have a fairly common, very reasonable use case that demonstrates what I believe to be a fundamental flaw in the relay cache/store update strategy.
Let's use these simplified types in the scenario:
```graphql
type SomeObject implements Node {
id: ID!
name: String
description: String
}
type SomeWrapper implements Node {
id: ID!
object: SomeObject
}
type Query {
get(id: ID!): SomeWrapper
search(term: String!): [SomeWrapper]
}
```
The important part here is that `SomeWrapper` references `SomeObject`.
In my use case, I have two `QueryRenderer`s: one to fetch search results, and one to fetch all the details of a selected object. They **must be independent queries** for 2 reasons:
1. the details query fetches MUCH more data than would be practical to return on all search results
2. search query should NOT be re-run each time the selected ID changes for the details query
Here's another heavily simplified description in GraphQL (in reality the queries are large, use the `Connection` spec, and are composed of many fragments):
```graphql
query SearchQuery ($term: String!) {
search (term: $term) {
id
object {
id
name
}
}
}
query DetailsQuery ($id: ID!) {
get (id: $id) {
id
object {
id
name
description
}
}
}
```
The important part here is that the `description` field is present in `DetailsQuery` but NOT in `SearchQuery`.
The problem comes when I have details pulled up for a `Wrapper` with ID `aaa`. It looks like this:
```json
{
"id": "aaa",
"object": {
"id": "111",
"name": "Name 1",
"description": "This is a HUGE piece of data."
}
}
```
Now, let's say that I do a search and receive results which contain `Wrapper` with ID `aaa`. It looks like this:
```json
[
{
"id": "aaa",
"object": {
"id": "111",
"name": "Name 1"
}
}
]
```
Nothing has changed, and this is great. However, let's say that `aaa` has changed to reference `Object` with ID `222`:
```json
[
{
"id": "aaa",
"object": {
"id": "222",
"name": "Name 2"
}
}
]
```
This becomes **EXTREMELY** problematic. Because `222` is new to relay, there is no cache for the `description` field, but the results for `DetailsQuery` are updated to reference it anyhow. While having a "description" go missing doesn't sound like a big deal, my real-world case has dozens of fields with nested queries. **Thus, receiving this kind of search result essentially makes the entire screen go blank.**
The problem, then, is that relay seems to split the middle between two more predictable updating strategies, where it would either:
1. NOT update the `DetailsQuery` results, since it knows that its cache is incomplete
2. Make a followup query to the required `node(id: ID!)` query root for the fields it knows are missing
I believe I can acheive the former by using separate environments, but this feels quite dirty.
If I recall correctly, the latter was the behavior in relay classic. Is there any way to restore this in modern?
I would be very interested to learn the reasoning behind the current behavior, and am willing to helping implement a better one if the relay team is open to the idea.
Contributor guide
Assessment
This issue has not been assessed yet.