3

ReactJS Pagination Tutorial: Building from Scratch

 3 years ago
source link: https://hackernoon.com/reactjs-pagination-tutorial-building-from-scratch-video-tr4g316w
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

ReactJS Pagination Tutorial: Building from Scratch

@codebucksCodeBucks

Helping you to learn code! here you'll find tutorials around web development. Keep Coding...😜

Hey Everyone,

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Hope you all doing great.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

In this post we're building pagination component from scratch in ReactJS. We're not going to use any library here.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

If you prefer to watch video then you can go through below video else keep reading...😄

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Let's start by creating our react-app,

npx create-react-app react-pagination-component

Create a separate file, like PaginationComponent.js.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Here, I'm using jsonplaceholder API to get data and use pagination on that data.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

This API will return us a list of todos. Now to store this data create one state and initialize it with an empty array.

0 reactions
heart.png
light.png
thumbs-down.png
money.png
const [data, setData] = useState([]);

Now let's use useEffect to set this state with our data which comes from API.

useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/todos")
      .then((response) => response.json())
      .then((json) => setData(json));
  }, []);

if you want to see what type of data this api is providing then just go to this url.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Also if you don't know how to fetch api in ReactJS you can watch my video on How to fetch API.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

let's create a small renderData component outside of our main component to render the "to-do" list.

0 reactions
heart.png
light.png
thumbs-down.png
money.png
import React, { useEffect, useState } from "react";
import "./style.css";

const renderData = (data) => {
  return (
    <ul>
      {data.map((todo, index) => {
        return <li key={index}>{todo.title}</li>;
      })}
    </ul>
  );
};

function PaginationComponent() {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/todos")
      .then((response) => response.json())
      .then((json) => setData(json));
  }, []);

  return (
    <>
      <h1>Todo List</h1> <br />
      {renderData(data)}
   
    </>
  );
}

export default PaginationComponent;

In const renderData here I have mapped title of to-dos from data state.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

and Render {renderData(data)} with data state, inside the return.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Now, let's create pagination from here.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

To do that we need two states,

0 reactions
heart.png
light.png
thumbs-down.png
money.png
const [currentPage, setcurrentPage] = useState(1);
const [itemsPerPage, setitemsPerPage] = useState(5);

currentPage :- stores current page number, initially 0.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

itemsPerPage :- stores no of items we want to display in single page. Initially it is 5.

0 reactions
heart.png
light.png
thumbs-down.png
money.png
  const pages = [];
  for (let i = 1; i <= Math.ceil(data.length / itemsPerPage); i++) {
    pages.push(i);
  }

In above code,

0 reactions
heart.png
light.png
thumbs-down.png
money.png

pages array contains total number of pages like 1,2,3..upto (total data / itemsPerPage).

0 reactions
heart.png
light.png
thumbs-down.png
money.png

If you have 20 items and you want to display 5 items per page then you will need 20/5 = 4 pages.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Let's create render page number component which will display page numbers.

0 reactions
heart.png
light.png
thumbs-down.png
money.png
import React, { useEffect, useState } from "react";
import "./style.css";

const renderData = (data) => {
  return (
    <ul>
      {data.map((todo, index) => {
        return <li key={index}>{todo.title}</li>;
      })}
    </ul>
  );
};

function PaginationComponent() {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/todos")
      .then((response) => response.json())
      .then((json) => setData(json));
  }, []);
  
  const handleClick = (event) => {
    setcurrentPage(Number(event.target.id));
  };
  
   const renderPageNumbers = pages.map((number) => { 
      return (
        <li
          key={number}
          id={number}
          onClick={handleClick}
          className={currentPage == number ? "active" : null}
        >
          {number}
        </li>
      );
    
  });
  

  return (
    <>
      <h1>Todo List</h1> <br />
      {renderData(data)}

      <ul className="pageNumbers">
       {renderPageNumbers}
      </ul>

    </>
  );
}

export default PaginationComponent;

As you can see after the handleClick method at renderPageNumber,

0 reactions
heart.png
light.png
thumbs-down.png
money.png

I have mapped this pages array which will return an

li  
tag which display page numbers. This
li
tag contains key, id, onClick method and className.
0 reactions
heart.png
light.png
thumbs-down.png
money.png

Here className becomes active when you are on the same page as currentPage state.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

This handleClick method runs when we click on any page number and set currentPage state to selected page number.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Now inside the return render renderPageNumbers component by wrapping it with

ul
tag and className as pageNumbers.
0 reactions
heart.png
light.png
thumbs-down.png
money.png

NOTE:For styling, you can refer this css file.

As you have observed, This page numbers are all over whole page and now we need to set limit to display this page numbers.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

To do that we need to define 3 more react states.

0 reactions
heart.png
light.png
thumbs-down.png
money.png
  const [pageNumberLimit, setpageNumberLimit] = useState(5);
  const [maxPageNumberLimit, setmaxPageNumberLimit] = useState(5);
  const [minPageNumberLimit, setminPageNumberLimit] = useState(0);

pageNumberLimit is to store how many page numbers you want to display. Here I want to display only 5.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

maxPageNumberLimit is to store max page bound limit.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

minPageNumberLimit is to store min page bound limit.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Now modify renderPageNumbers component by putting if condition like given below,

0 reactions
heart.png
light.png
thumbs-down.png
money.png
const renderPageNumbers = pages.map((number) => {
    if (number < maxPageNumberLimit + 1 && number > minPageNumberLimit) {
      return (
        <li
          key={number}
          id={number}
          onClick={handleClick}
          className={currentPage == number ? "active" : null}
        >
          {number}
        </li>
      );
    } else {
      return null;
    }
  });

This if condition means that if current number is greater then maxPageNumberLimit+1 and less then minPageNumberLimit then render it else render nothing.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

As you run your code, you will see that there are only 5 page numbers displayed.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Next we need next and previous buttons.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Create those buttons around the

{renderPageNumbers}
component.
0 reactions
heart.png
light.png
thumbs-down.png
money.png

Just like below,

0 reactions
heart.png
light.png
thumbs-down.png
money.png
import React, { useEffect, useState } from "react";
import "./style.css";

const renderData = (data) => {
  return (
    <ul>
      {data.map((todo, index) => {
        return <li key={index}>{todo.title}</li>;
      })}
    </ul>
  );
};

function PaginationComponent() {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/todos")
      .then((response) => response.json())
      .then((json) => setData(json));
  }, []);
  
  const handleClick = (event) => {
    setcurrentPage(Number(event.target.id));
  };
  
   const renderPageNumbers = pages.map((number) => { 
      return (
        <li
          key={number}
          id={number}
          onClick={handleClick}
          className={currentPage == number ? "active" : null}
        >
          {number}
        </li>
      );
    
  });
  
    const handleNextbtn = () => {
    setcurrentPage(currentPage + 1);

    if (currentPage + 1 > maxPageNumberLimit) {
      setmaxPageNumberLimit(maxPageNumberLimit + pageNumberLimit);
      setminPageNumberLimit(minPageNumberLimit + pageNumberLimit);
    }
  };

  const handlePrevbtn = () => {
    setcurrentPage(currentPage - 1);

    if ((currentPage - 1) % pageNumberLimit == 0) {
      setmaxPageNumberLimit(maxPageNumberLimit - pageNumberLimit);
      setminPageNumberLimit(minPageNumberLimit - pageNumberLimit);
    }
  };
  

  return (
    <>
      <h1>Todo List</h1> <br />
      {renderData(data)}

      <ul className="pageNumbers">
        <li>
          <button
            onClick={handlePrevbtn}
            disabled={currentPage == pages[0] ? true : false}
          >
            Prev
          </button>
        </li>
        {renderPageNumbers}
        <li>
          <button
            onClick={handleNextbtn}
            disabled={currentPage == pages[pages.length - 1] ? true : false}
          >
            Next
          </button>
        </li>
      </ul>

    </>
  );
}

export default PaginationComponent;

There are two buttons prev and next, before and above the

{renderPageNumbers}
.
0 reactions
heart.png
light.png
thumbs-down.png
money.png

In handleNextbtn method for next button. In this method whenever user clicks on next button, it will set the current page state to plus 1. and check the condition if current page has not crossed maximum page number limit or not. If yes then it will reset this max and min page number limit with new limit.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

In handlePrevbtn method for previous button. Only change is in the sign and in if condition. Suppose you are at page 6 and you want to go back to 5 then this condition will check that 6-1=5%5==0 so it will become true and it will reset max and min page number limits.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Below code is to disable next button,we will disable next button when user is at last page.

0 reactions
heart.png
light.png
thumbs-down.png
money.png
disabled={currentPage == pages[pages.length - 1] ? true:false}

Below code is to disable Prev button, we will disable prev button when user is at 1st page.

0 reactions
heart.png
light.png
thumbs-down.png
money.png
disabled={currentPage == pages[0] ? true : false}

Now our Pagination component is Almost completed one thing left is to add those three dots which indicates that there are more pages then displayed.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Let's create them.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Above is the full code for this Tutorial.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Just before the return I have created two buttons with hellip; which is unicode for ...

0 reactions
heart.png
light.png
thumbs-down.png
money.png

There are two buttons pageIncrementBtn will render when page length is > maxPageNumberLimit. while pageDecrementBtn will render when minPageNumberLimit >= 1.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Don't forget to render both of this ... buttons below and after the {renderPageNumbers} component.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Now your whole Pagination component is completed.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Watch above given video to know about one more pagination component which loads items vertically.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Thanks For Reading.😄

Also published here.

0 reactions
heart.png
light.png
thumbs-down.png
money.png
heart.pngheart.pngheart.pngheart.png
light.pnglight.pnglight.pnglight.png
boat.pngboat.pngboat.pngboat.png
money.pngmoney.pngmoney.pngmoney.png
Share this story
Join Hacker Noon

Create your free account to unlock your custom reading experience.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK