Paginationcomponent
The Storefront API uses cursors to paginate through lists of data and the <Pagination />
component makes it easy to paginate data from the Storefront API. It is important for pagination state to be maintained in the URL, so that the user can navigate to a product and return back to the same scrolled position in a list. It is also important that the list state is shareable via URL. The <Pagination>
component provides a render prop with properties to load more elements into your list.
Anchor to propsProps
- Anchor to connectionconnectionConnection<NodesType>required
The response from
storefront.query
for a paginated request. Make sure the query is passed pagination variables and that the query haswith
,
,
, and
defined.
- Anchor to childrenchildrenPaginationRenderProp<NodesType>required
A render prop that includes pagination data and helpers.
PaginationProps
- connection
The response from `storefront.query` for a paginated request. Make sure the query is passed pagination variables and that the query has `pageInfo` with `hasPreviousPage`, `hasNextpage`, `startCursor`, and `endCursor` defined.
Connection<NodesType>
- children
A render prop that includes pagination data and helpers.
PaginationRenderProp<NodesType>
{
/** The response from `storefront.query` for a paginated request. Make sure the query is passed pagination variables and that the query has `pageInfo` with `hasPreviousPage`, `hasNextpage`, `startCursor`, and `endCursor` defined. */
connection: Connection<NodesType>;
/** A render prop that includes pagination data and helpers. */
children: PaginationRenderProp<NodesType>;
}
Connection
{
nodes: Array<NodesType>;
pageInfo: PageInfo;
} | {
edges: Array<{
node: NodesType;
}>;
pageInfo: PageInfo;
}
PaginationRenderProp
- props
PaginationInfo<NodesType>
ReactNode
type PaginationRenderProp<NodesType> = (
props: PaginationInfo<NodesType>,
) => ReactNode;
PaginationInfo
- nodes
The paginated array of nodes. You should map over and render this array.
Array<NodesType>
- NextLink
The `<NextLink>` is a helper component that makes it easy to navigate to the next page of paginated data. Alternatively you can build your own `<Link>` component: `<Link to={nextPageUrl} state={state} preventScrollReset />`
(props: Omit<RemixLinkProps, "to"> & { ref?: Ref<HTMLAnchorElement>; }) => ReactNode
- PreviousLink
The `<PreviousLink>` is a helper component that makes it easy to navigate to the previous page of paginated data. Alternatively you can build your own `<Link>` component: `<Link to={previousPageUrl} state={state} preventScrollReset />`
(props: Omit<RemixLinkProps, "to"> & { ref?: Ref<HTMLAnchorElement>; }) => ReactNode
- previousPageUrl
The URL to the previous page of paginated data. Use this prop to build your own `<Link>` component.
string
- nextPageUrl
The URL to the next page of paginated data. Use this prop to build your own `<Link>` component.
string
- hasNextPage
True if the cursor has next paginated data
boolean
- hasPreviousPage
True if the cursor has previous paginated data
boolean
- isLoading
True if we are in the process of fetching another page of data
boolean
- state
The `state` property is important to use when building your own `<Link>` component if you want paginated data to continuously append to the page. This means that every time the user clicks "Next page", the next page of data will be apppended inline with the previous page. If you want the whole page to re-render with only the next page results, do not pass the `state` prop to the Remix `<Link>` component.
{ nodes: NodesType[]; pageInfo: { endCursor: string; startCursor: string; hasPreviousPage: boolean; }; }
interface PaginationInfo<NodesType> {
/** The paginated array of nodes. You should map over and render this array. */
nodes: Array<NodesType>;
/** The `<NextLink>` is a helper component that makes it easy to navigate to the next page of paginated data. Alternatively you can build your own `<Link>` component: `<Link to={nextPageUrl} state={state} preventScrollReset />` */
NextLink: (
props: Omit<LinkProps, 'to'> & {ref?: Ref<HTMLAnchorElement>},
) => ReactNode;
/** The `<PreviousLink>` is a helper component that makes it easy to navigate to the previous page of paginated data. Alternatively you can build your own `<Link>` component: `<Link to={previousPageUrl} state={state} preventScrollReset />` */
PreviousLink: (
props: Omit<LinkProps, 'to'> & {ref?: Ref<HTMLAnchorElement>},
) => ReactNode;
/** The URL to the previous page of paginated data. Use this prop to build your own `<Link>` component. */
previousPageUrl: string;
/** The URL to the next page of paginated data. Use this prop to build your own `<Link>` component. */
nextPageUrl: string;
/** True if the cursor has next paginated data */
hasNextPage: boolean;
/** True if the cursor has previous paginated data */
hasPreviousPage: boolean;
/** True if we are in the process of fetching another page of data */
isLoading: boolean;
/** The `state` property is important to use when building your own `<Link>` component if you want paginated data to continuously append to the page. This means that every time the user clicks "Next page", the next page of data will be apppended inline with the previous page. If you want the whole page to re-render with only the next page results, do not pass the `state` prop to the Remix `<Link>` component. */
state: {
nodes: Array<NodesType>;
pageInfo: {
endCursor: Maybe<string> | undefined;
startCursor: Maybe<string> | undefined;
hasPreviousPage: boolean;
};
};
}
Example code
examples
Example code
description
I am the default example
JavaScript
import {json} from '@shopify/remix-oxygen'; import {Pagination, getPaginationVariables} from '@shopify/hydrogen'; import {useLoaderData, Link} from '@remix-run/react'; export async function loader({request, context: {storefront}}) { const variables = getPaginationVariables(request, {pageBy: 8}); const data = await storefront.query(ALL_PRODUCTS_QUERY, { variables, }); return json({products: data.products}); } export default function List() { const {products} = useLoaderData(); return ( <Pagination connection={products}> {({nodes, PreviousLink, NextLink}) => ( <> <PreviousLink>Previous</PreviousLink> <div> {nodes.map((product) => ( <Link key={product.id} to={`/products/${product.handle}`}> {product.title} </Link> ))} </div> <NextLink>Next</NextLink> </> )} </Pagination> ); } const ALL_PRODUCTS_QUERY = `#graphql query AllProducts( $country: CountryCode $language: LanguageCode $first: Int $last: Int $startCursor: String $endCursor: String ) @inContext(country: $country, language: $language) { products(first: $first, last: $last, before: $startCursor, after: $endCursor) { nodes { id title handle } pageInfo { hasPreviousPage hasNextPage startCursor endCursor } } } `;
TypeScript
import {json, type LoaderArgs} from '@shopify/remix-oxygen'; import {Pagination, getPaginationVariables} from '@shopify/hydrogen'; import {useLoaderData, Link} from '@remix-run/react'; import {ProductConnection} from '@shopify/hydrogen/storefront-api-types'; export async function loader({request, context: {storefront}}: LoaderArgs) { const variables = getPaginationVariables(request, {pageBy: 8}); const data = await storefront.query<{products: ProductConnection}>( ALL_PRODUCTS_QUERY, { variables, }, ); return json({products: data.products}); } export default function List() { const {products} = useLoaderData<typeof loader>(); return ( <Pagination connection={products}> {({nodes, NextLink, PreviousLink}) => ( <> <PreviousLink>Previous</PreviousLink> <div> {nodes.map((product) => ( <Link key={product.id} to={`/products/${product.handle}`}> {product.title} </Link> ))} </div> <NextLink>Next</NextLink> </> )} </Pagination> ); } const ALL_PRODUCTS_QUERY = `#graphql query AllProducts( $country: CountryCode $language: LanguageCode $first: Int $last: Int $startCursor: String $endCursor: String ) @inContext(country: $country, language: $language) { products(first: $first, last: $last, before: $startCursor, after: $endCursor) { nodes { id title handle } pageInfo { hasPreviousPage hasNextPage startCursor endCursor } } } `;