Skip to main content

Remove fragmentSpreadName from visitedFragments when visit is complete

At a glance​

Timeline​


@robrichard raised an issue for @defer whereby under the current draft specification if you have this query:

query HeroNameQuery {
hero {
...NameFragment
...NameFragment @defer
}
}
fragment NameFragment on Hero {
name
}

then the @defer will never be visited; but if you move the @defer earlier:

query HeroNameQuery {
hero {
...NameFragment @defer
...NameFragment
}
}
fragment NameFragment on Hero {
name
}

then the non-deferred version will never be visited.


@mjmahone has an RFC open about fragment arguments which suffers a similar issue: visits to a fragment aren't equivalent depending on the variables.

query HeroNameQuery {
hero {
...ComponentOne
...ComponentTwo
}
}
fragment ComponentOne on Hero {
id
...HeroDetails(includeBio: true, includeAvatar: false)
}
fragment ComponentTwo on Hero {
...HeroDetails(includeBio: false, includeAvatar: true)
}
fragment HeroDetails($includeBio: Boolean!, $includeAvatar: Boolean!) on Hero {
superheroName
realName
initials
... @include(if: $includeAvatar) {
avatarLarge
avatarSmall
}
... @include(if: $includeBio) {
bioTitle
bioSubtitle
bioEntryParagraph
bioQuote
bioMainText
}
}

Matt's solution takes a Relay-esque approach and generates a key for the fragments based on the values of their arguments.


Another consideration is where there are user-defined directives; e.g. { id ...Profile name ...Profile @live } might benefit from walking Profile again now that it has @live attached.

A simple solution to this is rather than each of these problems having their own solution, to simply navigate the fragment spread again - it's only a single layer that we need to worry about, so the cost is likely to be marginal. This RFC proposes this with a tiny change to the spec - after adding the fragmentSpreadName to visitedFragments, and calling CollectFields, we then remove it again.