I have parent component that ends up with nested fragments looking like this:
query MyAppQuery(
$id
$a
$b
$c
) {
viewer {
...App_viewer
...ComponentA_viewer @include(if: $a)
...ComponentB_viewer @include(if: $b)
...ComponentC_viewer @include(if: $c)
}
allEmployees: allUsers(userType: "1") {
...ComponentA_allEmployees @include(if: $a)
...ComponentB_allEmployees @include(if: $b)
...ComponentC_allEmployees @include(if: $c)
}
};
Relay fails if I don't include all this child fragments but the data is the same for all these, it seems pretty dumb having to declare a view fragment on all my child components that require the signed in user.
How can I request this piece of data at the top of my application and have it available to child components without having to include the all these fragments.
This is starting to feel like reverse prop drilling with I have to declare a fragment at the lower end of my app and pass it up the chain.
Same with allEmployees. It's the same data that I should only get once and pass down or access through context but I have to pass in all these stupid fragments or relay complains.
This is a core pattern to Relay, and despite the verbosity, it is actually highly encouraged.
In Relay, child components are encouraged to specify their data requirements on their own in the form of fragments.
Ultimately, you're going to end up accumulating a lot of fragments that get spread elsewhere in your app, so it's worth pointing out a few key Relay features about why this is good:
Relay will not send duplicate requests to your API if you declare several fragments next to each other that request the same field(s). Instead, they will all get fetched once, in one round-trip. You don't have to worry about introducing overfetching/duplicate query problems, because they don't exist in Relay.
Relay introduces a compilation step via the Relay Compiler, that intelligently analyzes your GraphQL schema and any
graphql
template tags that you define in your code. This generates artifacts, which help manage fetching data and updating the Relay store automagically, so you don't have to. By declaring a lot of fragments, you are effectively telling the compiler and store about the data requirements of your components, even if they are the same/similar. Duplication here is what makes Relay great.Your QueryRenderer ancestor at the root of the tree will handle the actual fetching, and the fragments you've defined on child components lower in the tree instruct the Relay Compiler and Store where to send the data once it is fetched. This follows from #2.
So, in short, to make the most of Relay, declare your components' data requirements with fragments, and let Relay do the heavy lifting, and don't worry about duplication and lack of reusability. It is to your advantage.