Use when relay pagination with cursor-based pagination, infinite scroll, load more patterns, and connection protocols.
View on GitHubTheBushidoCollective/han
jutsu-relay
January 24, 2026
Select agents to install to:
npx add-skill https://github.com/TheBushidoCollective/han/blob/main/jutsu/jutsu-relay/skills/relay-pagination/SKILL.md -a claude-code --skill relay-paginationInstallation paths:
.claude/skills/relay-pagination/# Relay Pagination
Master Relay's cursor-based pagination for efficiently loading and displaying
large datasets with infinite scroll and load more patterns.
## Overview
Relay implements the GraphQL Cursor Connections Specification for efficient
pagination. It provides hooks like usePaginationFragment for declarative
pagination with automatic cache updates and connection management.
## Installation and Setup
### Pagination Query Structure
```graphql
# schema.graphql
type Query {
posts(
first: Int
after: String
last: Int
before: String
): PostConnection!
}
type PostConnection {
edges: [PostEdge!]!
pageInfo: PageInfo!
totalCount: Int
}
type PostEdge {
cursor: String!
node: Post!
}
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}
type Post {
id: ID!
title: String!
body: String!
}
```
## Core Patterns
### 1. Basic Pagination
```javascript
// PostsList.jsx
import { graphql, usePaginationFragment } from 'react-relay';
const PostsListFragment = graphql`
fragment PostsList_query on Query
@refetchable(queryName: "PostsListPaginationQuery")
@argumentDefinitions(
first: { type: "Int", defaultValue: 10 }
after: { type: "String" }
) {
posts(first: $first, after: $after)
@connection(key: "PostsList_posts") {
edges {
node {
id
...PostCard_post
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
`;
function PostsList({ query }) {
const {
data,
loadNext,
loadPrevious,
hasNext,
hasPrevious,
isLoadingNext,
isLoadingPrevious,
refetch
} = usePaginationFragment(PostsListFragment, query);
return (
<div>
<button
onClick={() => refetch({ first: 10 })}
disabled={isLoadingNext}
>
Refresh
</button>
{data.posts.edges.map(({ node }) => (
<PostCard key={node.id} post={node} />
))}