DEV Community

Cover image for Building Dynamic Table Pagination in React JS
Aneeqa Khan
Aneeqa Khan

Posted on

Building Dynamic Table Pagination in React JS

Table of contents

What is pagination?

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

First, I'll start with creating the basic structure of a table in react app with some pagination buttons.

      <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>
Enter fullscreen mode Exit fullscreen mode

Fetch data from API

I'm using an instantwebtools 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

  // 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]);

Enter fullscreen mode Exit fullscreen mode

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

  <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>
Enter fullscreen mode Exit fullscreen mode

It'll be showing like this
table

The logic behind pagination buttons

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.

  <button 
    onClick={() => setPage(0)} 
    disabled={isLoading || page === 0}
  >
    first
  </button>
Enter fullscreen mode Exit fullscreen mode

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

  <button
    onClick={() => setPage(page - 1)}
    disabled={isLoading || page === 0}
  >
    previous
  </button>
  <button
    onClick={() => setPage(page + 1)}
    disabled={isLoading || users.length < size}
  >
    next
  </button> 
Enter fullscreen mode Exit fullscreen mode

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.

  <button
    onClick={() => setPage(Math.round(count / size) - 1)}
    disabled={isLoading || users.length < size}
  >
    last
  </button>
Enter fullscreen mode Exit fullscreen mode

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

Here is the demo of react table with pagination


Thank you for reading!

Contact me

Top comments (0)