Learn how to navigate through lists of results using pagination.

Pagination enables the API to segment data into multiple result lists. This is crucial for both performance and user experience, as it allows the API to return only the data required at a given time.

Page Limit

All paginated API queries, SDK hooks, and methods accept an optional limit parameter. This parameter determines the number of items to return per page. The default value varies based on the query. The limit parameter is an enum with the following values:

enum LimitType {  Fifty = "Fifty",  Ten = "Ten",  TwentyFive = "TwentyFive",}

The limit parameter is an enum to enhance the caching efficiency of the results. Predictable responses facilitate better caching. If the limit parameter were a number, the API would need to cache results for every possible number, which would be inefficient.

If you require a different number of results, consider querying for a larger number and then filtering the items on the client side.

Cursor-Based Pagination

While we use the explorePublications query in all the examples below, the same principles apply to all other queries that return a list of results. There may be minor differences in the helpers offered by SDKs, but the overall concept remains the same.

The Lens React SDK simplifies cursor-based pagination and state management for you.

All paginated hooks return a PaginatedReadResult<T>. For instance, the useExplorePublications hook returns a PaginatedReadResult<ExplorePublication[]>.

Take note of the PaginatedReadResult wrapper around the results. This helper object provides additional methods to fetch the preceding and following pages of query results.

In the following example, we'll fetch the first 10 publications and display a button to fetch more publications if they are available.

import {  useExplorePublications,  ExplorePublicationsOrderByType,  LimitType} from '@lens-protocol/react-web';
function Pagination() {  const { data, error, hasMore, loading, next } = useExplorePublications({    orderBy: ExplorePublicationsOrderByType.Latest,    limit: LimitType.Ten,  });
  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;
  return (    <div>      <h1>        <code>Explore Publications</code>      </h1>      <div>        { => (          <div key={}>{}</div>        ))}        {hasMore && <button onClick={() => next()}>Next</button>}      </div>    </div>  );}

That's it—you've just learned how to use paginated results.


Some practical examples of how to use pagination in your application.

Infinite Scroll

You can create an infinite scroll experience by using a helper React Hook.

import {  useExplorePublications,  ExplorePublicationsOrderByType,  LimitType,} from "@lens-protocol/react-web";import { useInfiniteScroll } from "./useInfiniteScroll";
function Pagination() {  const { data, hasMore, observeRef } = useInfiniteScroll(    useExplorePublications({      orderBy: ExplorePublicationsOrderByType.Latest,      limit: LimitType.Ten,    })  );
  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;
  return (    <div>      <h1>        <code>Explore Publications</code>      </h1>      <div>        { => (          <div key={}>{}</div>        ))}        {hasMore && <p ref={observeRef}>Loading more...</p>}      </div>    </div>  );}

In this example, we used react-cool-inview to monitor the scroll position and trigger the next method when the user reaches the end of the page.

Pull to Refresh

The PaginatedReadResult object can be used to implement a "pull to refresh" feature. This is achieved by checking the value of beforeCount, which represents the number of items before the current page. If beforeCount is greater than zero, you can call the prev method to fetch the previous page of results.

import {  useExplorePublications,  ExplorePublicationsOrderByType,} from "@lens-protocol/react-web";
function Example() {  const { data, error, loading, hasMore, beforeCount, next, prev } =    useExplorePublications({      orderBy: ExplorePublicationsOrderByType.Latest,    });
  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;
  return (    <div>      {beforeCount > 0 && (        <button disabled={loading} onClick={prev}>          Fetch recent results        </button>      )}
      { => (        // render results        <div key={}>{}</div>      ))}
      {hasMore && (        <button disabled={loading} onClick={next}>          Load more        </button>      )}    </div>  );}