1

I'm learning to create data tables for a ReactJS / NextJS application without libraries.

I'm having a hard time paginating the table, can you please provide a code sample to handle this.

This is the table code I used:

const Table = () => {

  const data = [
    {name: 'Rara', profile: 'profile1', comment: 'comra'},
    {name: 'Dada', profile: 'profile2', comment: 'comda'},
    {name: 'Gaga', profile: 'profile1', comment: 'comga'},
    {name: 'Mama', profile: 'profile3', comment: 'comma'},
    {name: 'Papa', profile: 'profile4', comment: 'compa'},
    // ...
  ]

  const columns = [
    { id: 1, title: "Name", accessor: "name" },
    { id: 2, title: "Profile", accessor: "profile" },
    { id: 3, title: "Comment", accessor: "comment" },
  ];

  return (
    <table className={styles.container}>
      <thead>
        <tr>
          {columns.map((col) => (
            <th key={col.id}>{col.title}</th>
          ))}
        </tr>
      </thead>
      <tbody>
        {data.map((user, i) => (
          <tr key={i}>
            {columns.map((col) => (
              <td key={col.id}>{user[col.accessor]}</td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
};

I really appreciate any answer.

R.M. Reza
  • 725
  • 1
  • 8
  • 20
  • 1
    Please, take into account that paginating on the frontend could lead to some performance issues, for that reason I suggest paginating on the backend instead as suggested [here](https://stackoverflow.com/questions/54493353/is-it-better-to-paginate-on-the-server-side-or-front-end/54493622) – luckongas Jan 08 '21 at 12:13
  • Does this answer your question? [how to implement Pagination in reactJs](https://stackoverflow.com/questions/40232847/how-to-implement-pagination-in-reactjs) – luckongas Jan 08 '21 at 12:13
  • 1
    @luckongas Yes, for large amounts of data, this table only handles hundreds of data, thanks for the advice. – R.M. Reza Jan 08 '21 at 13:30

3 Answers3

0

Use Array#slice with an incremented page state. Something like this should get you started:


const Table = () => {

    // .....

    const itemsPerPage = 10;
    const [page, setPage] = useState(1);
    const displayData = useMemo(() => {
        const start = (page - 1) * itemsPerPage;
        return data.slice(start, start + itemsPerPage);
    }, [data]);

    // .....

    return (
        <>
            <button onClick={() => setPage(page + 1)}> Next Page </button>
            <button onClick={() => setPage(page - 1)}> Prev Page </button>

            { /* ..... */ }

              <tbody>
                {displayData.map((user, i) => (
                
             { /* ..... */ }


        </>
    );
};
mccallofthewild
  • 521
  • 2
  • 6
0

I did something a while ago with JS. Note: I'm not that good at React so some code may need to be corrected.

Here is a starting point

class table extends React.Component {



  const data = [{
      name: 'Rara',
      profile: 'profile1',
      comment: 'comra'
    },
    {
      name: 'Dada',
      profile: 'profile2',
      comment: 'comda'
    },
    {
      name: 'Gaga',
      profile: 'profile1',
      comment: 'comga'
    },
    {
      name: 'Mama',
      profile: 'profile3',
      comment: 'comma'
    },
    {
      name: 'Papa',
      profile: 'profile4',
      comment: 'compa'
    },
    // ...
  ]

  this.state = {
    selectedPage: 1,
    totalPages: 0,
    pageSize: 20
  }
  // totalPages should be comming from the database eg when you get the data from ajax, if you have all the data here then this should be good to go
  this.state.totalPages =Math.ceil((data.length - 1) / this.state.pageSize);
  const columns = [{
      id: 1,
      title: "Name",
      accessor: "name"
    },
    {
      id: 2,
      title: "Profile",
      accessor: "profile"
    },
    {
      id: 3,
      title: "Comment",
      accessor: "comment"
    },
  ];

 // get the data depending on which page you are on
  getData() {
    return data.slice(this.state.selectedPage * this.state.pageSize, this.state.pageSize);
  }


  // this should calculate the total viewed pagination eg prev 1 2 3 4 5 next
  paging() {

    if (!this.state.selectedPage || this.state.selectedPage > this.state.totalPages)
      this.state.selectedPage = 1;

    var start = this.state.selectedPage;
    var end = this.state.selectedPage;
    var counter = 3;
    //If the page cannot be devised by 5 enter the loop
    if ((start % counter != 0) && (end % counter != 0)) {
      //Get the next nearest page that is divisible by 5
      while ((end % counter) != 0) {
        end++;
      }
      //Get the previous nearest page that is divisible by 5
      while ((start % counter) != 0) {
        start--;
      }

    }
    //The page is divisible by 5 so get the next 5 pages in the pagination
    else {
      end += counter;
    }
    //We are on the first page
    if (start == 0) {
      start++;
      end++;
    }



    //We are on the last page
    if (end == this.state.totalPages || end > this.state.totalPages) {
      end = this.state.totalPages;
    }

    if (start == this.state.selectedPage && start > 1)
      start--;

    while (end - start < counter && end - start > 0)
      start--;


    if (start <= 0)
      start = 1;

    while (end - start > counter)
      end--;


    return {
      start: start,
      end: end
    };


  }


  jumToPage(e) {
    var s = this.state;
    s.selectedPage = parseInt(e.innerText);
    this.setState(s);
  }

  next() {
    var s = this.state;
    s.selectedPage += 1;
    this.setState(s);
  }

  prev() {
    var s = this.state;
    s.selectedPage -= 1;
    this.setState(s);
  }

  render() {
    var footerData = this.paging();

    return ( <
      table className = {
        styles.container
      } >
      <
      thead >
      <
      tr > {
        columns.map((col) => ( <
          th key = {
            col.id
          } > {
            col.title
          } < /th>
        ))
      } <
      /tr> < /
      thead > <
      tbody > {
        this.getData().map((user, i) => ( <
          tr key = {
            i
          } > {
            columns.map((col) => ( <
              td key = {
                col.id
              } > {
                user[col.accessor]
              } < /td>
            ))
          } <
          /tr>
        ))
      } <
      /tbody>  <
      tfoot > ( <
        tr >
        ( <
          td >
          <
          p onClick = {
            this.prev.bind(this)
          }
          className = {
            this.state.selectedPage <= 1 ? "disabled" : ""
          } > prev < /p> <
          /td>
        ) <
        /td>
        <td cols={columns.length - 2 }>
        for (var i = footerData.start; i < footerData.end; i++) { 
            <
            p onClick = {
              this.jumToPage.bind(this)
            } > {
              i
            } < /p>
        }
       </td>
      ) <
      td >
      ( <
        td >
        <
        p onClick = {
          this.next.bind(this)
        }
        className = {
          this.state.selectedPage >= this.state.totalPages ? "disabled" : ""
        } > next < /p> <
        /td>
      ) <
      /tr> <
      /tfoot> <
      /table>
    );
  }
};
Alen.Toma
  • 4,684
  • 2
  • 14
  • 31
0

So I was once tasked to make pagination for an API endpoint what I did was that I wrote a controller for handing that and the params taken were page and pageCount.

My endpoint: http://localhost:8000/api/icecream/:page/:pageCount

the page refers to the page on which you want the data (depends on pageCount) pageCount refers to the number of data you want on a single page.

So I just wrote a function that first retrieves the required data from DB as an array and then make subarrays depending upon the criteria provided as URL params.

The code looks like this:

module.exports.getIceCreamMenu = async function(req, res){
    try{
        const pageCount = parseInt(req.params.pageCount); // 10 flavours to be presented per page
        const page = parseInt(req.params.page); 
        const flavours = getFromDB(req.user.email); // fetching data from db as an array MONGODB

        var start = (page-1)*pageCount; // getting start point of the list
        var end = (pageCount*page); // getting end point of the list

        const requiredFlavourList = flavours.slice(start,end);
        res.json({success: true, flavours: requiredflavoursList});

    }catch(err){
        if(err) res.json({success: false, message: err.message});
    }
}
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103