In web applications—especially reporting or monitoring applications—we often need to display a large amount of data from an API. To make data loading faster, we typically design our APIs to support pagination.
In classic JavaScript _frameworks like _jQuery, we are familiar with using DataTables to display paginated data tables. But how do we use DataTables in ReactJS?
First, we create react application by executing in our terminal/CMD
npm create-react-app react-demo-datatable
Then in our terminal/CMD we have to install datatable package.
npm install react-data-table-component
Don't forget to install lodash.debounce package for our search data table. lodash.debounce is a utility function from the Lodash library that delays a function’s execution until after a specified amount of time has passed since it was last called. i will prevent Too many API calls (e.g. every user type) to Maximalize performance issue.
npm install lodash.debounce
Then let's adjust our App.js to look like this:
import React, { useState, useEffect } from "react"; import DataTable from "react-data-table-component"; import debounce from "lodash.debounce"; // Dummy local dataset const localData = [ { NO_RESI: "PLMAA16157522113", RECEIVER_NAME: "John Doe", RECEIVER_DIVISION: "IT", CREATED_DATE: "2025-04-11", STATUS_NAME: "Complete", STATUS: "002", }, { NO_RESI: "PLMAA16157522112", RECEIVER_NAME: "Jane Doe", RECEIVER_DIVISION: "Finance", CREATED_DATE: "2025-04-10", STATUS_NAME: "On Progress", STATUS: "001", }, // Add more dummy items here ]; const statusOptions = [ { key: "001", status: "On Progress" }, { key: "002", status: "Complete" }, ]; const columns = [ { name: "No Resi", selector: (row) => row.NO_RESI, sortable: true }, { name: "Receiver", selector: (row) => row.RECEIVER_NAME, sortable: true }, { name: "Receiver Division", selector: (row) => row.RECEIVER_DIVISION, sortable: true }, { name: "Created Date", selector: (row) => row.CREATED_DATE, sortable: true }, { name: "Status", selector: (row) => row.STATUS_NAME, sortable: true }, { name: "Action", cell: (row) => ( <button className="bg-blue-500 text-black px-3 py-1 rounded hover:bg-blue-600"> Detail </button> ), }, ]; const customStyles = { headCells: { style: { backgroundColor: "#919492", color: "#333", fontWeight: "bold", fontSize: "14px", }, }, }; export default function App() { const [data, setData] = useState([]); const [search, setSearch] = useState(""); const [statusFilter, setStatusFilter] = useState(""); const [loading, setLoading] = useState(false); const [totalRows, setTotalRows] = useState(0); const [perPage, setPerPage] = useState(10); const [currentPage, setCurrentPage] = useState(1); const filterLocalData = (page, size, searchText, statusKey) => { setLoading(true); let filtered = [...localData]; if (searchText) { filtered = filtered.filter( (item) => item.NO_RESI.toLowerCase().includes(searchText.toLowerCase()) || item.RECEIVER_NAME.toLowerCase().includes(searchText.toLowerCase()) ); } if (statusKey) { filtered = filtered.filter((item) => item.STATUS === statusKey); } const start = (page - 1) * size; const paginated = filtered.slice(start, start + size); setData(paginated); setTotalRows(filtered.length); setLoading(false); }; useEffect(() => { filterLocalData(currentPage, perPage, search, statusFilter); }, [search, statusFilter, perPage, currentPage]); const handlePageChange = (page) => { setCurrentPage(page); }; const handlePerRowsChange = (newPerPage, page) => { setPerPage(newPerPage); setCurrentPage(page); }; const debouncedSearch = debounce((val) => { setSearch(val); }, 500); return ( <div className="w-full p-4"> <div className="flex justify-between items-center mb-4 gap-4"> <select className="p-2 border rounded" value={statusFilter} onChange={(e) => setStatusFilter(e.target.value)} > <option value="">All Status</option> {statusOptions.map((opt) => ( <option key={opt.key} value={opt.key}> {opt.status} </option> ))} </select> <input type="text" placeholder="Search..." className="p-2 border rounded w-full max-w-md" onChange={(e) => debouncedSearch(e.target.value)} /> </div> <DataTable columns={columns} data={data} progressPending={loading} pagination paginationServer paginationTotalRows={totalRows} onChangePage={handlePageChange} onChangeRowsPerPage={handlePerRowsChange} customStyles={customStyles} /> </div> ); }
Our react project will look like this:
Top comments (0)