Building Dynamic Table Pagination in React JS
Tags: react, webdev, javascript, tutorial
Published: 2023-01-25 13:03:37

## Table of contents
* [What is pagination](#intro)
* [Create the structure of a table](#structure)
* [Fetch data from API](#fetch-data)
* [The logic behind pagination buttons](#logic-page)
* [Demo](#demo)

## What is pagination? <a name="intro"></a>
Pagination is a technique used to divide large data into smaller, more manageable chunks of data that can be accessed through navigation or links. This is often done by displaying a set number of rows per page, with links or buttons to navigate to other pages. 

## Create the structure of a table <a name="structure"></a>
First, I'll start with creating the basic structure of a table in react app with some pagination buttons.
```javascript
      <table>
        <thead>
          <tr>
            <th>ID</th>
            <th>First Name</th>
            <th>Number of trips</th>
          </tr>
        </thead>
        <tbody>
          // I'll display data here later
        </tbody>
      </table>
      <section>
        <button>first</button>
        <button>previous</button>
        <button>next</button>
        <button>last</button>
      </section>
```

## Fetch data from API <a name="fetch-data"></a>
I'm using an [instantwebtools](https://www.instantwebtools.net/fake-rest-api) website to fetch passenger's data.
> P.S. This API already have `totalPages` and `totalPassengers` props available. But I'll consider as only given prop is totalPassengers to calculate totalPages according to it.

But before that, I'll create some states
```javascript
  // number of records to show per page
  const size = 10; 
  // users data
  const [users, setUsers] = React.useState([]);
  // track page number 
  const [page, setPage] = React.useState(0);
  // total number of records 
  const [count, setCount] = React.useState(0);
  // track API response time
  const [isLoading, setIsLoading] = React.useState(false);

  const getUsers = React.useCallback(async () => {
    setIsLoading(true);
    const res = fetch(`${USERS_URL}?page=${page}&size=${size}`).then((res) =>
      res.json()
    );
    const json = await res;
    setIsLoading(false);
    setUsers(json.data);
    setCount(json.totalPassengers);
  }, [page]);

  React.useEffect(() => {
    getUsers();
  }, [getUsers]);

```
So I am using a `fetch` method to get API data and setting `users` and `count` states.

Now `map` the `users` in table body like this
```javascript
  <tbody>
    {users.map((user) => (
      <tr key={user._id}>
        <td className="table-data">{user._id}</td>
        <td className="table-data">{user.name}</td>
        <td className="table-data">{user.trips}</td>
      </tr>
    ))}
  </tbody>
```
It'll be showing like this
![table](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8qd19v8sz1fji82u3t3k.png)


## The logic behind pagination buttons <a name="logic-page"></a>
For the first page, I want to keep `page` value as 0 and also 0 is the least value so I want to disable the first button on the 0 value.
```javascript
  <button 
    onClick={() => setPage(0)} 
    disabled={isLoading || page === 0}
  >
    first
  </button>
```
next and previous buttons have quite familiar logic, I need to minus 1 from `page` for previous and add 1 for the next buttons like this
```javascript
  <button
    onClick={() => setPage(page - 1)}
    disabled={isLoading || page === 0}
  >
    previous
  </button>
  <button
    onClick={() => setPage(page + 1)}
    disabled={isLoading || users.length < size}
  >
    next
  </button> 
```
So here `next` button disable prop could be clearer. I'll explain it with an example.
> if total records are **29** and we are already on page **3**, on third page users array length will be **9** and size is **10** by default, so condition get `true` hence next button is disabled

For the last page, I'm dividing the `count` by `size` value and rounding the result.
```javascript
  <button
    onClick={() => setPage(Math.round(count / size) - 1)}
    disabled={isLoading || users.length < size}
  >
    last
  </button>
```
> for example if count/total records are **33** and size is **10**, result will be **3** after rounding it. So it means last page will be **2** after minus 1 and that's correct.

## Demo <a name="demo"></a>
Here is the demo of react table with pagination

{% codesandbox react-table-pagination-4irg12 %}
___

### Thank you for reading!
Contact me
- [Twitter](https://twitter.com/Aneeqa_Khan25)
- [LinkedIn](https://www.linkedin.com/in/aneeqa-khan-990459135/)
- [GitHub](https://github.com/AneeqaKhan)