Sick Gaming
[Tut] How to Build a React Data Table with Server-Side Pagination, Sorting and Search - Printable Version

+- Sick Gaming (https://www.sickgaming.net)
+-- Forum: Programming (https://www.sickgaming.net/forum-76.html)
+--- Forum: PHP Development (https://www.sickgaming.net/forum-82.html)
+--- Thread: [Tut] How to Build a React Data Table with Server-Side Pagination, Sorting and Search (/thread-103622.html)



[Tut] How to Build a React Data Table with Server-Side Pagination, Sorting and Search - xSicKxBot - 12-08-2025

[Tut] How to Build a React Data Table with Server-Side Pagination, Sorting and Search

<div style="margin: 5px 5% 10px 5%;"><img src="https://www.sickgaming.net/blog/wp-content/uploads/2025/12/how-to-build-a-react-data-table-with-server-side-pagination-sorting-and-search.jpg" width="550" height="401" title="" alt="" /></div><div><div class="modified-on" readability="7.1304347826087"> by <a href="https://phppot.com/about/">Vincy</a>. Last modified on October 29th, 2025.</div>
<p>The React TanStack table is a great tool for displaying an elegant view of data table. It provides enriched features to build list with impressive user experience.</p>
<p>This tutorial uses <strong>Server-side data fetching and rendering, searching and sorting</strong> features.</p>
<p>A shopping cart product table is created in the backend. It has basic details to be listed in a tabular form. The React app connects to the PHP API to connect this database to fetch the rows.</p>
<p>The React TanStack <a href="https://phppot.com/jquery/responsive-datatables-with-automatic-column-hiding/">data table shows these data rows</a> in the front end as shown below.</p>
<p><img decoding="async" loading="lazy" class="alignnone size-large wp-image-24411" src="https://phppot.com/wp-content/uploads/2025/10/react-data-table-db-rows-550x401.jpg" alt="react data table db rows" width="550" height="401" srcset="https://phppot.com/wp-content/uploads/2025/10/react-data-table-db-rows-550x401.jpg 550w, https://phppot.com/wp-content/uploads/2025/10/react-data-table-db-rows-300x219.jpg 300w, https://phppot.com/wp-content/uploads/2025/10/react-data-table-db-rows-768x560.jpg 768w, https://phppot.com/wp-content/uploads/2025/10/react-data-table-db-rows.jpg 1245w" sizes="auto, (max-width: 550px) 100vw, 550px"></p>
<h2>Setting up the React TanStack table example code</h2>
<p>This command is used to install the React TanStack data table library.</p>
<pre class="prettyprint"><code class="language-makefile">npm install @tanstack/react-table
</code></pre>
<p>This will add the following library reference to the application’s package config.</p>
<pre class="prettyprint"><code class="language-json">npm install @tanstack/react-table "dependencies": { "@tanstack/react-table": "^8.21.3", ... ... },
</code></pre>
<p>If you are going to run this example in your environment, follow the below steps to set up. It has all the build required for the React TanStack data table rendering.</p>
<ol>
<li>Download and extract the React project bundle.</li>
<li>Go to the React project directory by <code>cd react-data-table-server-side-pagination-sorting-search</code></li>
<li>Run <code>npm install</code> to create <code>node_modules</code>.</li>
<li>Copy <code>/api/react-product-table-api/</code> to your PHP root and configure in React JSX.</li>
<li>Create database <code>db_shopping_cart</code> and import <code>sql/database.sql</code></li>
</ol>
<p>Then, start the dev server by using <code>npm run dev</code>.</p>
<h2>How to initiate React TanStack data table?</h2>
<p>This is to initiate React TabStack library using <code class="language-jsx">useReactTable</code>. It adds the raw data reference to the TanStack library row column object to render data.</p>
<p class="code-heading"><code>Part of TanStack.jsx</code></p>
<pre class="prettyprint"><code class="language-jsx">import { useEffect, useState, useCallback } from "react";
import axios from "axios";
import { useReactTable, getCoreRowModel, getSortedRowModel, flexRender,
} from "@tanstack/react-table";
import "./TanStack.css"; const TanStack = () =&amp;gt; { const [data, setData] = useState([]); const [search, setSearch] = useState(""); const [page, setPage] = useState(1); const [limit, setLimit] = useState(5); const [total, setTotal] = useState(0); const [sortBy, setSortBy] = useState("id"); const [order, setOrder] = useState("asc"); ... //Fetch Data ... useEffect(() =&amp;gt; { fetchData(); }, [fetchData]); const columns = [ { header: "S.No", accessorKey: "sno", cell: (info) =&amp;gt; (page - 1) * limit + info.row.index + 1, }, { header: "Title", accessorKey: "title", cell: (info) =&amp;gt; info.getValue(), }, { header: "Price", accessorKey: "price", cell: (info) =&amp;gt; `$${info.getValue()}`, }, { header: "Category", accessorKey: "category", cell: (info) =&amp;gt; info.getValue(), }, ]; const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), }); ... ...
}
</code></pre>
<h2>Designing the table layout and components</h2>
<p>There are three major UI parts in this React data table example.</p>
<ol>
<li>The tabular view.</li>
<li>Search bar.</li>
<li>Footer <a href="https://phppot.com/php/ajax-pagination-with-tabular-records-using-php-and-jquery/">pagination component</a>.</li>
</ol>
<h3>1. The tabular view</h3>
<p><img decoding="async" loading="lazy" class="alignnone size-large wp-image-24409" src="https://phppot.com/wp-content/uploads/2025/10/react-tanstack-table-filter-550x232.jpg" alt="react tanstack table filter" width="550" height="232" srcset="https://phppot.com/wp-content/uploads/2025/10/react-tanstack-table-filter-550x232.jpg 550w, https://phppot.com/wp-content/uploads/2025/10/react-tanstack-table-filter-300x127.jpg 300w, https://phppot.com/wp-content/uploads/2025/10/react-tanstack-table-filter-768x324.jpg 768w, https://phppot.com/wp-content/uploads/2025/10/react-tanstack-table-filter.jpg 1335w" sizes="auto, (max-width: 550px) 100vw, 550px"></p>
<p class="code-heading"><code>Table header - Part of TanStack.jsx</code></p>
<pre class="prettyprint"><code class="language-php-template">&lt;th key={header.id} className={alignClass} onClick={() =&gt; key !== "sno" &amp;&amp; handleSort(key) } style={{ cursor: key === "sno" ? "default" : "pointer", }}
&gt;
{flexRender(header.column.columnDef.header, header.getContext())} {key !== "sno" &amp;&amp; sortBy === key &amp;&amp; (order === "asc" ? ( &lt;img src="/icons/up.svg" alt="asc" style={{ width: "14px", height: "14px", marginLeft: "5px", verticalAlign: "middle", }} /&gt; ) : ( &lt;img src="/icons/down.svg" alt="desc" style={{ width: "14px", height: "14px", marginLeft: "5px", verticalAlign: "middle", }} /&gt; ))}
&lt;/th&gt;
</code></pre>
<p>This section has the TanStack script for iterating the table row array using <code>table.gerRowModel()</code> reference.</p>
<p>The <code>flexRender</code> function loads the table cell data in a row.</p>
<p class="code-heading"><code>Table body rows in TanStack.jsx</code></p>
<pre class="prettyprint"><code class="language-php-template">&lt;tbody&gt; {table.getRowModel().rows.length &gt; 0 ? ( table.getRowModel().rows.map((row) =&gt; ( &lt;tr key={row.id}&gt; {row.getVisibleCells().map((cell) =&gt; { const key = cell.column.columnDef.accessorKey; const alignClass = key === "price" ? "price" : key === "sno" ? "center" : ""; return ( &lt;td key={cell.id} className={alignClass}&gt; {flexRender(cell.column.columnDef.cell, cell.getContext())} &lt;/td&gt; ); })} &lt;/tr&gt; )) ) : ( &lt;tr&gt; &lt;td colSpan={columns.length}&gt;No data found&lt;/td&gt; &lt;/tr&gt; )}
&lt;/tbody&gt;
</code></pre>
<h3>2. Search Container</h3>
<p>It is a usual HTML input that sets the <a href="https://phppot.com/php/advanced-search-using-php/">search keyword on-change</a>. When the search is on, it resets the current-page value back to 1.</p>
<p class="code-heading"><code>Search input JSX in TanStack.jsx</code></p>
<pre class="prettyprint"><code class="language-html">&lt;div className="search-container"&gt; &lt;img src="/icons/search.svg" alt="search" className="search-icon" /&gt; &lt;input type="text" placeholder="Search by title..." value={search} onChange={(e) =&gt; { setSearch(e.target.value); setPage(1); }} className="search-input" /&gt;
&lt;/div&gt;
</code></pre>
<h3>3. Pagination</h3>
<p>This component returns JSX with numbered buttons with <a href="https://phppot.com/php/how-to-add-pagination-in-php-with-mysql/">a previous-next pagination link</a> to move the row pointer back and forth.</p>
<p class="code-heading"><code>Pagination JSX</code></p>
<pre class="prettyprint"><code class="language-html">&lt;div className="pagination-container"&gt; &lt;button className="pagination-btn" onClick={() =&gt; setPage((prev) =&gt; Math.max(prev - 1, 1))} disabled={page === 1} &gt; &lt;img src="/icons/back.svg" alt="Previous" className="pagination-icon" /&gt; Prev &lt;/button&gt; &lt;span className="pagination-info"&gt; Page {page} of {totalPages || 1} &lt;/span&gt; &lt;button className="pagination-btn" onClick={() =&gt; setPage((prev) =&gt; (prev &lt; totalPages ? prev + 1 : prev))} disabled={page &gt;= totalPages} &gt; Next &lt;img src="/icons/forward.svg" alt="Next" className="pagination-icon" /&gt; &lt;/button&gt; &lt;select value={limit} onChange={(e) =&gt; { setLimit(Number(e.target.value)); setPage(1); }} className="pagination-select" &gt; {[5, 10, 20, 50].map((num) =&gt; ( &lt;option key={num} value={num}&gt; {num} / page &lt;/option&gt; ))} &lt;/select&gt;
&lt;/div&gt;
</code></pre>
<p><img decoding="async" loading="lazy" class="alignnone size-large wp-image-24413" src="https://phppot.com/wp-content/uploads/2025/10/paginated-results-with-react-data-table-550x327.jpg" alt="paginated results with react data table" width="550" height="327" srcset="https://phppot.com/wp-content/uploads/2025/10/paginated-results-with-react-data-table-550x327.jpg 550w, https://phppot.com/wp-content/uploads/2025/10/paginated-results-with-react-data-table-300x178.jpg 300w, https://phppot.com/wp-content/uploads/2025/10/paginated-results-with-react-data-table-768x456.jpg 768w, https://phppot.com/wp-content/uploads/2025/10/paginated-results-with-react-data-table.jpg 1279w" sizes="auto, (max-width: 550px) 100vw, 550px"></p>
<h2>Fetching Data from the Server API</h2>
<p>This is the place to configure the server-side API URL to connect to the database for <a href="https://phppot.com/jquery/using-jqgrid-control-with-php/">displaying dynamic grid</a>. It sets the data array for the TanStack initiation.</p>
<p>This example has a single endpoint that receives all the search, sort and pagination inputs. The following React useCallback() passes these parameters to the API.</p>
<p>The React callback hook sets the raw data for the TanStack’s getCoreRowModel block to build a table row instance.</p>
<p class="code-heading"><code>Part of TanStack.jsx</code></p>
<pre class="prettyprint"><code class="language-php">const fetchData = useCallback(async () =&gt; { try { const res = await axios.get("http://localhost/react-product-table-api/products.php", { params: { search, page, limit, sortBy, order }, }); const fetchedData = res.data.data || res.data.products || []; setData(fetchedData); setTotal(res.data.total || 0); } catch (err) { console.error("Error fetching data:", err); }
}, [search, page, limit, sortBy, order]);
</code></pre>
<p>Below PHP script shows how to process a request from the allowed React origin. This PHP service prepares the SELECT query based on the search keyword, current page and sorting column &amp; order passed from the React frontend.</p>
<p class="code-heading">react-product-table-api/products.php</p>
<pre class="prettyprint"><code class="language-php">&lt;?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json");
require_once "db.php"; $page = $_GET['page'] ?? 1;
$limit = $_GET['limit'] ?? 5;
$search = $_GET['search'] ?? '';
$sortBy = $_GET['sortBy'] ?? 'id';
$order = $_GET['order'] ?? 'asc';
$offset = ($page - 1) * $limit; $allowedSort = ['id', 'title', 'price', 'category'];
$allowedOrder = ['asc', 'desc']; if (!in_array($sortBy, $allowedSort)) $sortBy = 'id';
if (!in_array(strtolower($order), $allowedOrder)) $order = 'asc'; $sql = "SELECT * FROM products WHERE title LIKE ? ORDER BY $sortBy $order LIMIT ?, ?";
$stmt = $conn-&gt;prepare($sql);
$searchParam = "%$search%";
$stmt-&gt;bind_param("sii", $searchParam, $offset, $limit);
$stmt-&gt;execute();
$result = $stmt-&gt;get_result(); $data = [];
while ($row = $result-&gt;fetch_assoc()) { $data[] = $row;
} $countSql = "SELECT COUNT(*) AS total FROM products WHERE title LIKE ?";
$countStmt = $conn-&gt;prepare($countSql);
$countStmt-&gt;bind_param("s", $searchParam);
$countStmt-&gt;execute();
$countResult = $countStmt-&gt;get_result()-&gt;fetch_assoc(); echo json_encode([ "products" =&gt; $data, "total" =&gt; $countResult["total"]
]);
?&gt;</code></pre>
<h2>Conclusion</h2>
<p>This example built a front end React data table with search, sort and pagination features. The <a href="https://tanstack.com/table/latest/docs/introduction" target="_blank" rel="noopener">TanStack table library</a> provides more features apart these three features. For example, it has column ordering, row selection, resizing and more. But, we covered the prime features of this library that are need in majority of the frontend tables.</p>
<p><strong>References</strong></p>
<ol>
<li><a href="https://tanstack.com/table/latest/docs/installation" target="_blank" rel="noopener">TanStack table installation guidelines</a></li>
<li><a href="https://www.pencilandpaper.io/articles/ux-pattern-analysis-enterprise-data-tables" target="_blank" rel="noopener">Data table design patterns</a></li>
</ol>
<p><a class="download" href="https://phppot.com/downloads/react/react-data-table-server-side-pagination-sorting-search.zip">Download</a></p>
<div class="written-by" readability="9.8427672955975">
<div class="author-photo"> <img loading="lazy" decoding="async" src="https://phppot.com/wp-content/themes/solandra/images/Vincy.jpg" alt="Vincy" width="100" height="100" title="Vincy"> </div>
<div class="written-by-desc" readability="14.764150943396"> Written by <a href="https://phppot.com/about/">Vincy</a>, a web developer with 15+ years of experience and a Masters degree in Computer Science. She specializes in building modern, lightweight websites using PHP, JavaScript, React, and related technologies. Phppot helps you in mastering web development through over a decade of publishing quality tutorials. </div>
</p></div>
<p> <!-- #comments --> </p>
<div class="related-articles">
<h2>Related Tutorials</h2>
</p></div>
<p> <a href="https://phppot.com/react/react-data-table-server-side-pagination-sorting-search/#top" class="top">↑ Back to Top</a> </p>
</div>


https://www.sickgaming.net/blog/2025/10/29/how-to-build-a-react-data-table-with-server-side-pagination-sorting-and-search/