so, let's say I have a "master/detail"-ish architecture, where my UI has a section for a specific user, and within that section is a page that shows that user's followers. it's at a route like /users/:username/followers
.
in my component hierarchy, this works with something like
<FollowersPage> <-- top level route component, matched by react-router
<UserSectionWrapper> <-- renders the outer wrapper for the user section
<FollowersList /> <-- the inner content of the page
</UserSectionWrapper>
</FollowersPage>
<UserSectionWrapper />
renders some basic information about a user, such as their display name and avatar. <FollowersList />
renders the list of their followers.
Now, how I was hoping to structure this, using GraphQL, was to have <UserSectionWrapper />
wrapped with a higher-order GraphQL component:
const userQuery = gql`
query User($username: String!) {
user(username: $username) {
id
displayName
avatar
}
}
`;
const withUser = graphql<any, Props>(userQuery, {
options: (props: Props) => {
return {
variables: {
username: props.username,
},
};
},
});
And also wrap <FollowersList />
in a similar HOC:
const followersQuery = gql`
query Followers($username: String!) {
user(username: $username) {
followers {
id
username
displayName
}
}
}
`;
const withFollowers = graphql<any, Props>(followersQuery, {
options: (props: Props) => {
return {
variables: {
username: props.username,
},
};
},
});
However, the problem with this is that it makes a separate GraphQL request for each component. This is bad.
So, my assumption is that I need to move the queries into the top-level <FollowersPage/ >
. Then, I can either pass down the data into my component tree, or continue using the HoCs as-written and just rely on the Apollo cache to avoid remaking the requests.
So, what's the best way to structure this? Can I write, like, a UserSectionWrapper
query, and a FollowersList
query, and then combine them into a FollowersPage
query? Is this what "fragments" are for? The Apollo docs are confusing on this (I think partially because it assumes I have a greater understanding of GraphQL than I do).
Yeah so how I handle this is to create a fragment which can be spread into the User query. I don't want the entirety of the user document within my followers, so I then use
filter
fromgraphql-anywhere
to filter the results of the User query based on my fragment. We actually do this filtering in a higher-order component and userecompose
to ultimately pass the data down toFollowers
- such that props.followers is hydrated outside of the component.gql/fragments/followers.js
gql/queries/user.js
components/User/index.js
components/Followers/index.js