Skip to content

Instantly share code, notes, and snippets.

@chaddjohnson
Last active November 16, 2020 02:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save chaddjohnson/9e91b8e50043989583ab49e4b2096950 to your computer and use it in GitHub Desktop.
Save chaddjohnson/9e91b8e50043989583ab49e4b2096950 to your computer and use it in GitHub Desktop.
React Pagination Example Using Hooks
import React, { useEffect } from 'react';
const fetcher = (url) => fetch(url).then((response) => response.json());
const useFavoriteRecipes = ({ page, pageSize }) => {
// This will re-fetch when the dynamic URL below changes.
// SWR documentation: https://github.com/vercel/swr
const {
data: favoriteRecipes,
error: favoriteRecipesError,
mutate: fetchFavoriteRecipes,
} = useSWR(`/favorites/recipes?page=${page}&pageSize=${pageSize}`, fetcher);
const favoriteRecipesLoading = !recipes && !error;
// Initial fetch.
useEffect(() => {
fetchFavoriteRecipes();
}, []);
return {
favoriteRecipes,
favoriteRecipesError,
favoriteRecipesLoading,
fetchFavoriteRecipes,
};
};
export default useFavoriteRecipes;
import React, { useState } from 'react';
import { useRouter } from 'next/router';
const FavoriteRecipesPage = () => {
const { router } = useRouter();
const [page, setPage] = useState(router.query.page);
const [pageSize, setPageSize] = useState(router.query.pageSize);
const { favoriteRecipes } = useFavoriteRecipes({ page, pageSize });
const handlePaginationChange = (newPage, newPageSize) => {
setPage(newPage);
setPageSize(newPageSize);
};
return (
<>
<h1>Favorite Recipes</h1>
<ul>
{favoriteRecipes.data.map(({ title }, index) => (
<li key={index}>{title}</li>
))}
</ul>
<Pagination
path={router.pathname}
page={page}
pageSize={pageSize}
total={favoriteRecipes.total}
onPaginationChange={handlePaginationChange}
/>
</>
);
};
export default FavoriteRecipesPage;
import React, { useState, useEffect } from 'react';
const Pagination = ({
path,
page,
pageSize,
total,
onPaginationChange,
}) => {
const pageCount = Math.ceil(total / pageSize);
const handlePreviousClick = (event) => {
event.preventDefault();
onPaginationChange(page - 1, pageSize);
};
const handleClick = (event, newPage) => {
event.preventDefault();
onPaginationChange(newPage, pageSize);
};
const handleNextClick = (event) => {
event.preventDefault();
onPaginationChange(page + 1, pageSize);
};
const handlePageSizeChange = (newPageSize) => {
onPaginationChange(page, newPageSize);
};
return (
<div>
{page > 0 ? (
<a
href={`${path}?page=${page - 1}&pageSize=${pageSize}`}
onClick={handlePreviousClick}
>
Previous
</a>
) : (
<button disabled>Previous</button>
)}
{[...Array(pageCount).keys()].map((pageIndex) => (
<a
href={`${path}?page=${pageIndex}&pageSize=${pageSize}`}
onClick={handleClick}
>
{pageIndex + 1}
</a>
))}
{page >= pageCount ? (
<a
href={`${path}?page=${page + 1}&pageSize=${pageSize}`}
onClick={handleNextClick}
>
Next
</a>
) : (
<button disabled>Next</button>
)}
<label>
Per Page
<select value={pageSize} onChange={handlePageSizeChange}>
<option value={5}>5</option>
<option value={10}>10</option>
<option value={25}>25</option>
<option value={50}>50</option>
<option value={100}>100</option>
</select>
</label>
</div>
);
};
export default Pagination;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment