ReactJS Datatable
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) => ( Detail ), }, ]; 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 ( setStatusFilter(e.target.value)} > All Status {statusOptions.map((opt) => ( {opt.status} ))} debouncedSearch(e.target.value)} /> ); }

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) => (
),
},
];
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 (
debouncedSearch(e.target.value)}
/>
);
}