DEV Community

Discussion on: Relay: the GraphQL client that wants to do the dirty work for you

Collapse
 
rosavage profile image
Ro Savage

Great article, thanks Gabriel. Love these in-depth posts!

One thing I've never understood about relay is how to have a fragment request data that the fragment above it doesn't know about.

In your example, imagine the fragment that contains the tags. It would look something like

      const blogPostTags = useFragment<BlogPostHeader_blogTags>(
        graphql`
          fragment BlogPostTags_blogPost on BlogPost {
            tags  {
                 slug
                 shortName
             }
          }
        `,
        blogPost
      );

Now, imagine from this component we also wanted to be able to change add a new tag. So now we need not just the tags that the blog has, but all available tags.

If weren't using Fragments we could write a top level query that might look like

blog {
   tags { 
     slug
     shortName
   }
   blogPostById(id: $blogPostId) {
     tags {
       slug
       shortName
     }
   }
}

However, because we are using relay fragments the only way would be to pass down account from our top level query. But the BlogPost and BlogHeader don't require account. So we end up just passing account through two components that have no idea why they require account.

Now you can take this futher, maybe you have a <TagPicker /> component that can be re-used everywhere. It only requests tags { slug, shortName } but can be dozens of components down from the top level query where Blog {} is originally asked and where the fragment needs to be destructured.

Is there a nice way Relay can solve this?

Three solutions I've used is
1) Have the <TagPicker /> have query the graphql endpoint directly. But then I have unnecessary extra requests and repeated requests for the exact same data.
2) Have the <TagPicker /> use context to have the relay $key passed down without prop-drilling. However this causes race conditions when relay receives new data, and expects that the component will have it but because context hasn't re-rendered yet it's actually empty.
3) Prop-drilling down a dozen components, which makes refactoring very hard.