-
Notifications
You must be signed in to change notification settings - Fork 15
Description
TL;DR: I believe smart clients like Relay, which maintain a normalized cache, could leverage CCN’s ?
to prevent cache corruption due to null bubbling
The Problem
Null bubbling (when a error or null value encountered in a non-nullable field bubbles up to a parent nullable field) is destructive. It causes true and correct data that could be included in the response to be omitted. This can cause problems when trying to write a GraphQL response into a normalized cache.
Imagine two cards A and B side by side, each of which contain information about the current user. A shows “name” and B shows “age”. They are powered by two different queries. The response for query A looks like this:
{ // Response A
"data": {
"me": { "id": "10", "name": "Jordan}
}
}
We can write this into our normalized cache and it will look like:
{ // Normalized cache
"ROOT": {
"me": {__id: "10"}
},
"10": {
"id": "10",
"name": "Jordan"
}
}
This is fine, and we can nicely render our first card.
Now, however, we get an error in our second query’s response:
{ // Response B
"data": {
"me": null // <-- Null due to bubbling
}
"errors": [{ "message": "Age errored", "path": ["me", "age"] }]
}
The age field, which was non-nullable, has errored, and we won’t be able to render our second card. Oh well, such is life. However, when we go to write this into our cache, things get worse:
{ // Normalized cache
"ROOT": {
"me": null // <-- We had to write null here!
},
"10": {
"id": "10",
"name": "Jordan"
}
}
Now card A, which also reads from this normalized store, is broken despite the fact that none of the fields it reads are in an error state.
A possible solution
With the adoption of Relay’s proposed error handling feature, product code is shielded from implicit field errors via framework-level explicit error handling. This means Relay is no-longer dependent on the server’s response shape strictly matching the schema. Specifically, it’s fine for a field marked as an error to be missing, even if it’s non-nullable. In other words, Relay can safely opt-out of server-side null bubbling.
And CCN's ?
offers Relay just that option. Relay’s compiler can annotate every non-null field in the query it generates with a ?
to opt out of any null bubbling.
Note: I’ve documented the CCN behavior I’m expecting here.
A new world
Lets now imagine how response B would look like in this new world:
{ // Response B (without null bubbling)
"data": {
"me": {
"id": "10",
"age": null // <-- Errored, but did not bubble!
}
}
"errors": [{
"message": "Age errored",
"path": ["me", "age"]
}]
}
When we write this into our normalized cache we get:
{ // Normalized cache
"ROOT": {
"me": {__id: "10"}
},
"10": {
"id": "10",
"name": "Jordan"
"age": Error("Age errored")
}
}
Card B still can’t render, but note that we’ve prevented our normalized cache from getting corrupted due to null bubbling. Thanks CCN!
Related
This post is spiritually related to #19 in that they both explore the benefits of a mode of GraphQL execution that avoids null bubbling. It may be worth exploring other mechanisms where-by clients could opt out of null bubbling, but I wanted to point out that CCN’s ?
is a powerful enough primitive to allow a smart client like Relay to opt out of null bubbling.
Hat tip to @RyanHoldren who wrote an excellent internal post articulating this normalization issue. My note here is very much inspired by that post.