-
-
Save radiumrasheed/fee539a591ab17217d0ae4fff6750566 to your computer and use it in GitHub Desktop.
React Table Server side Pagination and Filtering
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import "regenerator-runtime/runtime"; | |
import { useState } from "react"; | |
import { useAsyncDebounce } from "react-table"; | |
const ColumnFilter = ({ column }) => { | |
const { filterValue, setFilter } = column; | |
const [value, setValue] = useState(filterValue); | |
const onChange = useAsyncDebounce((value) => { | |
setFilter(value || undefined); | |
}, 300); | |
return ( | |
<span> | |
<input | |
className="border-0 h-6 w-full text-black" | |
placeholder="Search" | |
value={value || ""} | |
onChange={(e) => { | |
setValue(e.target.value); | |
onChange(e.target.value); | |
}} | |
/> | |
</span> | |
); | |
}; | |
export default ColumnFilter; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// TODO: Fix babel -> ReferenceError: regeneratorRuntime is not defined | |
import "regenerator-runtime/runtime"; | |
import { useState } from "react"; | |
import { useAsyncDebounce } from "react-table"; | |
const GlobalFilter = ({ filter, setFilter }) => { | |
const [value, setValue] = useState(filter); | |
const onChange = useAsyncDebounce((value) => { | |
setFilter(value || undefined); | |
}, 300); | |
return ( | |
<span> | |
Search:{" "} | |
<input | |
className="border h-10 mb-5 w-72" | |
value={value || ""} | |
onChange={(e) => { | |
setValue(e.target.value); | |
onChange(e.target.value); | |
}} | |
/> | |
</span> | |
); | |
}; | |
export default GlobalFilter; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// TODO: fix the below key issue | |
/* eslint-disable react/jsx-key */ | |
import { useState, useEffect, useMemo, useCallback } from "react"; | |
import { | |
useTable, | |
usePagination, | |
useGlobalFilter, | |
useFilters, | |
} from "react-table"; | |
import Spinner from "../shared/Spinner"; | |
import GlobalFilter from "./GlobalFilter"; | |
import ColumnFilter from "./ColumnFilter"; | |
import { COLUMNS } from "./columns"; | |
import styles from "./ViewAllStudents.module.css"; | |
const ViewAllStudents = () => { | |
const PAGE_NO = 0; | |
const [recordsPerPage, setRecordsPerPage] = useState(50); | |
const [totalPage, setTotalPages] = useState(1); | |
const [tableData, setTableData] = useState([]); | |
const [loading, setLoding] = useState(false); | |
const columns = useMemo(() => COLUMNS, []); | |
const defaultColumn = useMemo( | |
() => ({ | |
Filter: ColumnFilter, | |
}), | |
[] | |
); | |
const fetchStudentsData = useCallback( | |
async (pageNo, recordsPerPage, searchText = "", filters) => { | |
try { | |
const res = await fetch( | |
`/api/student?pageNo=${pageNo}&recordsPerPage=${recordsPerPage}&searchText=${searchText}&filters=${JSON.stringify( | |
filters | |
)}` | |
); | |
const json = await res.json(); | |
setTableData(json?.data?.students || []); | |
setTotalPages(json?.data?.totalPages || 1); | |
setLoding(false); | |
} catch (err) {} | |
}, | |
[] | |
); | |
const { | |
getTableProps, | |
getTableBodyProps, | |
headerGroups, | |
rows, | |
prepareRow, | |
page, | |
canPreviousPage, | |
canNextPage, | |
pageOptions, | |
pageCount, | |
gotoPage, | |
nextPage, | |
previousPage, | |
setPageSize, | |
setGlobalFilter, | |
// Get the state from the instance | |
state: { pageIndex, pageSize, globalFilter, filters }, | |
} = useTable( | |
{ | |
columns, | |
data: tableData, | |
defaultColumn, | |
manualPagination: true, | |
manualGlobalFilter: true, | |
manualFilters: true, | |
initialState: { | |
pageIndex: PAGE_NO, | |
pageSize: recordsPerPage, | |
}, | |
pageCount: totalPage, | |
}, | |
useFilters, | |
useGlobalFilter, | |
usePagination | |
); | |
useEffect(() => { | |
setLoding(true); | |
fetchStudentsData(pageIndex + 1, recordsPerPage, globalFilter, filters); | |
}, [pageIndex, recordsPerPage, globalFilter, fetchStudentsData, filters]); | |
useEffect(() => { | |
setRecordsPerPage(pageSize); | |
gotoPage(0); | |
}, [pageSize, gotoPage]); | |
return ( | |
<div> | |
<GlobalFilter filter={globalFilter} setFilter={setGlobalFilter} /> | |
<div className="p-2"> | |
<button | |
className="bg-zinc-300 p-1 mx-2" | |
onClick={() => gotoPage(0)} | |
disabled={!canPreviousPage} | |
> | |
{"<<"} | |
</button> | |
<button | |
className="bg-zinc-300 p-1 mx-2" | |
onClick={() => previousPage()} | |
disabled={!canPreviousPage} | |
> | |
{"<"} | |
</button> | |
<button | |
className="bg-zinc-300 p-1 mx-2" | |
onClick={() => nextPage()} | |
disabled={!canNextPage} | |
> | |
{">"} | |
</button> | |
<button | |
className="bg-zinc-300 p-1 mx-2" | |
onClick={() => gotoPage(pageCount - 1)} | |
disabled={!canNextPage} | |
> | |
{">>"} | |
</button> | |
<span> | |
Page{" "} | |
<strong> | |
{pageIndex + 1} of {pageOptions.length} | |
</strong> | |
</span> | |
<span> | |
| Go to page: | |
<input | |
type="number" | |
value={pageIndex + 1} | |
onChange={(e) => { | |
const page = e.target.value ? Number(e.target.value) - 1 : 0; | |
gotoPage(page); | |
}} | |
style={{ width: "100px" }} | |
/> | |
</span> | |
<select | |
value={pageSize} | |
onChange={(e) => { | |
setPageSize(Number(e.target.value)); | |
}} | |
> | |
{[10, 20, 30, 40, 50].map((pageSize) => ( | |
<option key={pageSize} value={pageSize}> | |
Show {pageSize} | |
</option> | |
))} | |
</select> | |
</div> | |
{loading ? ( | |
<Spinner /> | |
) : ( | |
<div className="max-w-full overflow-x-scroll"> | |
<table className={styles.table} {...getTableProps()}> | |
<thead> | |
{headerGroups.map((headerGroup) => ( | |
<tr {...headerGroup.getHeaderGroupProps()}> | |
{headerGroup.headers.map((column) => ( | |
<th | |
className={styles.cell} | |
{...column.getHeaderProps({ | |
style: { | |
minWidth: column.minWidth, | |
width: column.width, | |
}, | |
})} | |
> | |
{column.render("Header")} | |
<div> | |
{column.canFilter && column.id !== "_id" | |
? column.render("Filter") | |
: null} | |
</div> | |
</th> | |
))} | |
</tr> | |
))} | |
</thead> | |
<tbody {...getTableBodyProps()}> | |
{rows.map((row) => { | |
prepareRow(row); | |
return ( | |
<tr {...row.getRowProps()}> | |
{row.cells.map((cell) => { | |
return ( | |
<td | |
className={styles.cell} | |
{...cell.getCellProps({ | |
style: { | |
minWidth: cell.minWidth, | |
width: cell.width, | |
}, | |
})} | |
> | |
{cell.render("Cell")} | |
</td> | |
); | |
})} | |
</tr> | |
); | |
})} | |
</tbody> | |
</table> | |
</div> | |
)} | |
</div> | |
); | |
}; | |
export default ViewAllStudents; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment