Basic Dynamic Client Side Table Pagination with reactstrap

Gift Hove
About Coding
Published in
5 min readJun 19, 2019
Pagination with reactstrap

When you are developing in Reactjs there are times when it is worth looking at other libraries for packed and well-tested components rather than developing your own components from scratch. Some of these components are very stable and have been in existence for quite some time. Reactstrap is an example of a very stable library that has some common reusable components that one can make use of.

Reactstrap has pre-built Stateless React Components for Bootstrap 4 that allow a great deal of flexibility and Pagination is one of them.

I have lots of data which I am displaying in an HTML table (the dataset is not big enough to warrant server-side paging). For easier data visualization and navigation, I decided to add pagination to the data and I looked at the ReactStrap pagination suite of components for a quick solution. I am using Bootstrap for styling my application and this is a bonus since the reactstrap library has been built to use bootstrap.

In essence, pagination is a simple navigation technique that allows you to chop huge amounts of data within your tables into smaller subsets that can be easily navigated. I will illustrate how I used reactstrap in my solution for pagination. In this article, I will assume that you know how to setup a react application and I will concentrate only on the reactstrap pagination bit.

Including reactstrap in the app.

You will need to install reactstrap and its dependencies in your application. The reactstrap documentation has all the steps, and they are very easy to follow. Read the documentation here.

  1. Before you can use reactstrap you need to have Bootstrap installed in your application. To install bootstrap run the npm script below:
Install Bootstrap

2. After installing Bootstrap, install reactstrap in your application by running the npm script below in your terminal

Install Reactstrap

Using reactstrap Pagination, PaginationItem and PaginationLink

I decided to create an outer wrapper dumb component called TablePagination.js which wraps the pagination artefacts together. To do that:

  1. Create a javascript file called TablePagination.js and then import the React from react and PropTypes from prop-types.
  2. Import the named imports Pagination, PaginationItem and PaginationLink from reactstrap.

Below is the code for the TablePagination.js

  1. I used an arrow function to create the component.
  2. The component takes 5 props which are all defined in the propTypes. See below:
TablePagination.propTypes = {
pagesCount: PropTypes.number.isRequired,
currentPage: PropTypes.number.isRequired,
handlePageClick: PropTypes.func.isRequired,
handlePreviousClick: PropTypes.func.isRequired,
handleNextClick: PropTypes.func.isRequired
};

a.) pageCount: the total number of records in our dataset.

b.) currentPage: the current page navigated to

c.) handlePageClick: a function that handles the click event when a page number is clicked. This function will pass the current page number which will be saved in state.

d.) handlePreviousClick: a function that handles the click event when the previous button is clicked. This enables navigating to the previous(<<) page.

e.) handleNextClick: a function that handles the click event when the next (>>) button is clicked. This enables navigating to the next page.

3. I used object destructuring of the props object, to pass down the properties as variables. This improves readability by getting rid of props. By just looking at the signature you can see what properties are required by the component.

const TablePagination = ({
pagesCount,
currentPage,
handlePageClick,
handlePreviousClick,
handleNextClick
}) => ( ...)

4. The reactstrap Pagination component encapsulates the reactstrap PaginationItem which in turn encapsulates reactstrap PaginationLink.

5. The first PaginationItem inside the Pagination is the previous button. This is disabled when the current page is zero or less than zero “disabled={currentPage <= 0}”. I also pass the handlePreviousClick to it which handles the click event of the previous button.

<PaginationItem disabled={currentPage <= 0}>
<PaginationLink onClick={handlePreviousClick} previous href="#" /></PaginationItem>

6. The next PaginationItem after the previous PaginationItem button is the dynamic PaginationItem. This is the one that generates the page number buttons.

Array(pagesCount)”: creates and initializes a new array object of length equal to pagesCount.

[…Array(pagesCount)].map( fn)”: using the spread operator I expand the array. After expanding, the map() method then creates a new array of PaginationItems. See the snippet below.

{[...Array(pagesCount)].map((page, i) => (
<PaginationItem active={i === currentPage} key={i}>
<PaginationLink onClick={e => handlePageClick(e, i)} href="#">
{i + 1}
</PaginationLink>
</PaginationItem>
))}

Using and Combining the TablePagination Component with a Table with Records

I have a set of registration data called registrations. This array of registrations is passed to the RegistrationList component on props. See the complete RegistrationList component below.

This component is defined by the use of an arrow function. The first thing you will notice is that this component is using useState react hook to manage the state of the currentPage. See snippet for line 7 below.

const [currentPage, setCurrentPage] = useState(0);

Page size is set to 10 in this example. However, pagesCount is calculated by dividing the number of records by the pageSize and using Math.Ceil function on the result to round it to the nearest largest whole number.

When you click a page number on the pager, the currentPage number is set to the currently clicked page number using the function below which in turn is passed to the TablePagination component on props.

const handlePageClick = (e, index) => {
e.preventDefault();
setCurrentPage(index);
};

Now, let’s have a look at the snippet below. To work out which records to display, the registrations are sliced starting at a position calculated by multiplying the currentPage selected and the pageSize. So if the current page is 2 we will start at position 20 in the registrations array. The end position of the slice is calculated by (currentPage + 1) * pageSize. Using the current page as 2 we will end at position 30.

<tbody>
{registrations
.slice(currentPage * pageSize, (currentPage + 1) * pageSize)
.map(registration => {
return (
<tr key={registration.id}>
<td>
<a className="btn btn-light">View</a>
</td>
<td>
<Link to={"/registration/" + registration.id}>
registration.attendee.title}
</Link>
</td>
<td>{registration.attendee.firstName}</td>
<td>{registration.attendee.lastName}</td>
</tr>
);
})}
</tbody>

To show the result

This simple pagination can be enhanced to be done server side. The illustration here is to get you started. Reactstrap documentation has more than enough information on how to use the components.

I hope this helps and happy coding!

--

--