Skip to main content
The usePagination hook provides the logic to build custom pagination components.

Import

import { usePagination } from 'react-instantsearch';

Parameters

totalPages
number
Maximum number of pages to display. By default, all pages are shown.
const { pages } = usePagination({ totalPages: 20 });
padding
number
default:"3"
Number of pages to show around the current page.
const { pages } = usePagination({ padding: 2 });

Returns

currentRefinement
number
The current page number (0-indexed).
const { currentRefinement } = usePagination();
console.log(currentRefinement); // 0 for first page
refine
(page: number) => void
Function to navigate to a specific page.
const { refine } = usePagination();
refine(5); // Go to page 6 (0-indexed)
pages
number[]
Array of page numbers to display based on padding.
const { pages } = usePagination();
console.log(pages); // [0, 1, 2, 3, 4]
nbHits
number
Total number of hits.
const { nbHits } = usePagination();
console.log(nbHits); // 1234
nbPages
number
Total number of pages.
const { nbPages } = usePagination();
console.log(nbPages); // 25
isFirstPage
boolean
Whether the current page is the first page.
const { isFirstPage } = usePagination();
isLastPage
boolean
Whether the current page is the last page.
const { isLastPage } = usePagination();
canRefine
boolean
Whether pagination can be applied (more than one page).
const { canRefine } = usePagination();
if (!canRefine) return null;
createURL
(page: number) => string
Function to create a URL for a specific page.
const { createURL } = usePagination();
const url = createURL(5);

Examples

Basic Pagination

import { usePagination } from 'react-instantsearch';

function Pagination() {
  const { pages, currentRefinement, refine } = usePagination();

  return (
    <div className="pagination">
      {pages.map((page) => (
        <button
          key={page}
          onClick={() => refine(page)}
          disabled={page === currentRefinement}
        >
          {page + 1}
        </button>
      ))}
    </div>
  );
}

With Previous/Next Buttons

import { usePagination } from 'react-instantsearch';

function PaginationWithControls() {
  const {
    pages,
    currentRefinement,
    refine,
    isFirstPage,
    isLastPage,
  } = usePagination();

  return (
    <div className="pagination">
      <button
        onClick={() => refine(currentRefinement - 1)}
        disabled={isFirstPage}
      >
        Previous
      </button>
      {pages.map((page) => (
        <button
          key={page}
          onClick={() => refine(page)}
          className={page === currentRefinement ? 'active' : ''}
        >
          {page + 1}
        </button>
      ))}
      <button
        onClick={() => refine(currentRefinement + 1)}
        disabled={isLastPage}
      >
        Next
      </button>
    </div>
  );
}

With First/Last Buttons

import { usePagination } from 'react-instantsearch';

function FullPagination() {
  const {
    pages,
    currentRefinement,
    nbPages,
    refine,
    isFirstPage,
    isLastPage,
  } = usePagination();

  return (
    <div className="pagination">
      <button onClick={() => refine(0)} disabled={isFirstPage}>
        First
      </button>
      <button
        onClick={() => refine(currentRefinement - 1)}
        disabled={isFirstPage}
      >
        Previous
      </button>
      {pages.map((page) => (
        <button
          key={page}
          onClick={() => refine(page)}
          className={page === currentRefinement ? 'active' : ''}
        >
          {page + 1}
        </button>
      ))}
      <button
        onClick={() => refine(currentRefinement + 1)}
        disabled={isLastPage}
      >
        Next
      </button>
      <button onClick={() => refine(nbPages - 1)} disabled={isLastPage}>
        Last
      </button>
    </div>
  );
}

With Page Info

import { usePagination } from 'react-instantsearch';

function PaginationWithInfo() {
  const {
    pages,
    currentRefinement,
    nbPages,
    nbHits,
    refine,
  } = usePagination();

  const hitsPerPage = 20;
  const firstHit = currentRefinement * hitsPerPage + 1;
  const lastHit = Math.min((currentRefinement + 1) * hitsPerPage, nbHits);

  return (
    <div>
      <p>
        Showing {firstHit}-{lastHit} of {nbHits} results
      </p>
      <div className="pagination">
        {pages.map((page) => (
          <button
            key={page}
            onClick={() => refine(page)}
            className={page === currentRefinement ? 'active' : ''}
          >
            {page + 1}
          </button>
        ))}
      </div>
      <p>
        Page {currentRefinement + 1} of {nbPages}
      </p>
    </div>
  );
}

Compact Pagination

import { usePagination } from 'react-instantsearch';

function CompactPagination() {
  const {
    currentRefinement,
    nbPages,
    refine,
    isFirstPage,
    isLastPage,
  } = usePagination();

  return (
    <div className="compact-pagination">
      <button
        onClick={() => refine(currentRefinement - 1)}
        disabled={isFirstPage}
      >

      </button>
      <span>
        {currentRefinement + 1} / {nbPages}
      </span>
      <button
        onClick={() => refine(currentRefinement + 1)}
        disabled={isLastPage}
      >

      </button>
    </div>
  );
}

With Ellipsis

import { usePagination } from 'react-instantsearch';

function PaginationWithEllipsis() {
  const { pages, currentRefinement, nbPages, refine } = usePagination({
    padding: 2,
  });

  const showFirstEllipsis = pages[0] > 0;
  const showLastEllipsis = pages[pages.length - 1] < nbPages - 1;

  return (
    <div className="pagination">
      {showFirstEllipsis && (
        <>
          <button onClick={() => refine(0)}>1</button>
          <span>...</span>
        </>
      )}
      {pages.map((page) => (
        <button
          key={page}
          onClick={() => refine(page)}
          className={page === currentRefinement ? 'active' : ''}
        >
          {page + 1}
        </button>
      ))}
      {showLastEllipsis && (
        <>
          <span>...</span>
          <button onClick={() => refine(nbPages - 1)}>{nbPages}</button>
        </>
      )}
    </div>
  );
}

Jump to Page

import { usePagination } from 'react-instantsearch';
import { useState } from 'react';

function PaginationWithJump() {
  const { currentRefinement, nbPages, refine, pages } = usePagination();
  const [inputPage, setInputPage] = useState('');

  const handleJump = (e) => {
    e.preventDefault();
    const page = parseInt(inputPage, 10) - 1;
    if (page >= 0 && page < nbPages) {
      refine(page);
      setInputPage('');
    }
  };

  return (
    <div>
      <div className="pagination">
        {pages.map((page) => (
          <button
            key={page}
            onClick={() => refine(page)}
            className={page === currentRefinement ? 'active' : ''}
          >
            {page + 1}
          </button>
        ))}
      </div>
      <form onSubmit={handleJump}>
        <input
          type="number"
          min="1"
          max={nbPages}
          value={inputPage}
          onChange={(e) => setInputPage(e.target.value)}
          placeholder="Jump to page..."
        />
        <button type="submit">Go</button>
      </form>
    </div>
  );
}
import { usePagination } from 'react-instantsearch';
import Link from 'next/link';

function LinkPagination() {
  const { pages, currentRefinement, refine, createURL } = usePagination();

  return (
    <div className="pagination">
      {pages.map((page) => (
        <Link
          key={page}
          href={createURL(page)}
          onClick={(e) => {
            e.preventDefault();
            refine(page);
          }}
          className={page === currentRefinement ? 'active' : ''}
        >
          {page + 1}
        </Link>
      ))}
    </div>
  );
}

Minimal Pagination

import { usePagination } from 'react-instantsearch';

function MinimalPagination() {
  const { canRefine } = usePagination();

  if (!canRefine) {
    return null;
  }

  return <FullPagination />;
}

TypeScript

import { usePagination } from 'react-instantsearch';
import type { UsePaginationProps } from 'react-instantsearch';

function Pagination(props?: UsePaginationProps) {
  const { pages, currentRefinement, refine } = usePagination(props);

  return (
    <div>
      {pages.map((page) => (
        <button
          key={page}
          onClick={() => refine(page)}
          disabled={page === currentRefinement}
        >
          {page + 1}
        </button>
      ))}
    </div>
  );
}

Notes

Page numbers are 0-indexed internally but typically displayed as 1-indexed to users.
Algolia limits results to 1000 hits by default. Configure paginationLimitedTo in your index settings if you need more pages.