Rendering Connections
In Relay, in order to display a list of data that is backed by a GraphQL connection, first you need to declare a fragment that queries for a connection:
const {graphql} = require('RelayModern');
const userFragment = graphql`
fragment UserFragment on User {
name
friends(after: $cursor, first: $count)
@connection(key: "UserFragment_friends") {
edges {
node {
...FriendComponent
}
}
}
}
`;
- In the example above, we're querying for the
friendsfield, which is a connection; in other words, it adheres to the connection spec. Specifically, we can query theedgesandnodes in the connection; theedgesusually contain information about the relationship between the entities, while thenodes are the actual entities at the other end of the relationship; in this case, thenodes are objects of typeUserrepresenting the user's friends. - In order to indicate to Relay that we want to perform pagination over this connection, we need to mark the field with the
@connectiondirective. We must also provide a static unique identifier for this connection, known as thekey. We recommend the following naming convention for the connection key:<fragment_name>_<field_name>. - We will go into more detail later as to why it is necessary to mark the field as a
@connectionand give it a uniquekeyin our Updating Connections section.
In order to render this fragment which queries for a connection, we can use the usePaginationFragment Hook:
import type {FriendsListPaginationQuery} from 'FriendsListPaginationQuery.graphql';
import type {FriendsListComponent_user$key} from 'FriendsList_user.graphql';
const React = require('React');
const {Suspense} = require('React');
const {graphql, usePaginationFragment} = require('react-relay');
type Props = {
user: FriendsListComponent_user$key,
};
function FriendsListComponent(props: Props) {
const {data} = usePaginationFragment<FriendsListPaginationQuery, _>(
graphql`
fragment FriendsListComponent_user on User
@refetchable(queryName: "FriendsListPaginationQuery") {
name
friends(first: $count, after: $cursor)
@connection(key: "FriendsList_user_friends") {
edges {
node {
...FriendComponent
}
}
}
}
`,
props.user,
);
return (
<>
{data.name != null ? <h1>Friends of {data.name}:</h1> : null}
<div>
{/* Extract each friend from the resulting data */}
{(data.friends?.edges ?? []).map(edge => {
const node = edge.node;
return (
<Suspense fallback={<Glimmer />}>
<FriendComponent user={node} />
</Suspense>
);
})}
</div>
</>
);
}
module.exports = FriendsListComponent;
usePaginationFragmentbehaves the same way as auseFragment(see the Fragments section), so our list of friends is available underdata.friends.edges.node, as declared by the fragment. However, it also has a few additions:- It expects a fragment that is a connection field annotated with the
@connectiondirective - It expects a fragment that is annotated with the
@refetchabledirective. Note that@refetchabledirective can only be added to fragments that are "refetchable", that is, on fragments that are onViewer, onQuery, on any type that implementsNode(i.e. a type that has anidfield), or on a@fetchabletype.
- It expects a fragment that is a connection field annotated with the
- It takes two Flow type parameters: the type of the generated query (in our case
FriendsListPaginationQuery), and a second type which can always be inferred, so you only need to pass underscore (_).
Is this page useful?
Help us make the site even better by answering a few quick questions.