I want to build pagination the proper way that is SEO-friendly and liked by google. From doing my research, it seems that there is a lot of incorrect content out there that, while it works, is poor for SEO. I assume that, because of my SEO-friendly requirement, I cannot use any state to manage the next/prev page links and so on, and I want the page to use URL params to determine the page number (e.g. /something?page=2). It sounds like /something/page/2 might also be acceptable, but I prefer URL params, especially as Facebook seems to use it so it must be a good way of doing so.
The problem is that my solution seems to have to use <a/> tags, which obviously just inefficiently reload the entire page when clicked on. When I try to replace the a tags with Link tags, the pagination stops working, and the component does not re-render when clicking on the prev/next links (but strangely, according to the react dev tools, re-renders all of the other components not in this demo, so something key must be wrong).
Here is my paginator component:
interface PaginatorProps {
currentPage: number;
itemCount: number;
itemsPerPage?: number;
path: string;
}
export const Paginator: FC<PaginatorProps> = ({
currentPage,
itemCount,
itemsPerPage,
path,
}) => {
const totalPages: number = Math.ceil(itemCount / itemsPerPage);
const disablePrev: boolean = currentPage <= 1;
const disableNext: boolean = currentPage >= totalPages; // is last page (or 'above')
if (totalPages <= 1 || !totalPages || !itemsPerPage || currentPage > totalPages) {
return null;
}
let next: string = path,
prev: string = path;
if (currentPage + 1 <= itemCount) {
next = `${path}?page=${currentPage + 1}`;
}
if (currentPage - 1 >= 1) {
prev = `${path}?page=${currentPage - 1}`;
}
return (
<div>
<Link to={prev} className={`${disablePrev ? 'disabled' : ''}`}>
Prev
</Link>
<span className={'paginationStyles.currentPage'}>
Page {currentPage} of {totalPages}
</span>
<Link to={next} className={`${disableNext ? 'disabled' : ''}`}>
Next
</Link>
</div>
);
};
And an example component that uses it:
export const DataList = () => {
const itemsPerPage: number = 3;
const urlParams: URLSearchParams = new URLSearchParams(window.location.search);
const currentPage: number = Number(urlParams.get('page')) || 1;
const skip: number = (currentPage - 1) * itemsPerPage;
const { dataCount, data, loading, error } = useGetDataList({ limit: itemsPerPage, skip });
if (loading) return <Loading />;
if (error) return <Error msg={error} />;
if (!data?.length) return <p>No data found...</p>;
return (
<>
<ul>
{data.map(({ email }) => (
<li key={email}>{email}</li>
))}
</ul>
<Paginator
currentPage={currentPage}
itemCount={dataCount}
itemsPerPage={itemsPerPage}
path='/user/profile/affiliate/data-list'
/>
</>
);
};
Does anyone know how to make it re-render the component and paginate properly? Or is this the wrong approach per se?