When adding basic sorting and filtering functionalities my react-table component doesn't render - javascript

I have a basic react-table component which works without sort and filter but when I add these two functionalities it gets an error:
> publicUtils.js:205 Uncaught Error: Renderer Error ☝️
> at Object.render (publicUtils.js:205)
> at reactTable.js:31
> at Array.map (<anonymous>)
> at ReactTable (reactTable.js:29)
> at renderWithHooks (react-dom.development.js:16305)
> at updateFunctionComponent (react-dom.development.js:19588)
> at beginWork (react-dom.development.js:21601)
> at HTMLUnknownElement.callCallback (react-dom.development.js:4164)
> at Object.invokeGuardedCallbackDev (react-dom.development.js:4213)
> at invokeGuardedCallback (react-dom.development.js:4277)
The working code is the following:
import React from "react";
import { useTable, useSortBy, useFilters } from "react-table";
function ReactTable({ columns, data }) {
const tableInstance = useTable({ columns, data }, useFilters, useSortBy);
return (
<table {...tableInstance.getTableProps()}>
<thead>
{tableInstance.headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th {...column.getHeaderProps()}>{column.render("Header")}</th>
))}
</tr>
))}
</thead>
<tbody {...tableInstance.getTableBodyProps()}>
{tableInstance.rows.map((row) => {
tableInstance.prepareRow(row);
return (
<tr {...row.getRowProps()}>
{row.cells.map((cell) => (
<td {...cell.getCellProps()}>{cell.render("Cell")}</td>
))}
</tr>
);
})}
</tbody>
</table>
);
}
export default ReactTable;
If I replace that with the following code it stops working:
import React from "react";
import { useTable, useSortBy, useFilters } from "react-table";
function ReactTable({ columns, data }) {
const tableInstance = useTable({ columns, data }, useFilters, useSortBy);
return (
<table {...tableInstance.getTableProps()}>
<thead>
{tableInstance.headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th
{...column.getHeaderProps(column.getSortByToggleProps())}
>
{column.render("Header")}
<span>
{column.isSorted
? column.isSortedDesc
? " 🔽"
: " 🔼"
: ""}
</span>
</th>
))}
</tr>
))}
<tr>
{tableInstance.columns.map((column) => (
<th key={column.accessor}>
{column.canFilter ? column.render("Filter") : null}
</th>
))}
</tr>
</thead>
<tbody {...tableInstance.getTableBodyProps()}>
{tableInstance.rows.map((row) => {
tableInstance.prepareRow(row);
return (
<tr {...row.getRowProps()}>
{row.cells.map((cell) => (
<td {...cell.getCellProps()}>{cell.render("Cell")}</td>
))}
</tr>
);
})}
</tbody>
</table>
);
}
export default ReactTable;
What am I doing wrong? The columns and data are exactly the same. I even put the failing code in chatGPT and it told me it was fine. Any idea what I am doing wrong? Thank you.

Related

How can I ensure the refresh of a sub component's props?

I have a problem with RTK queries : I have a first component that encapsulates a table. When a refresh occurs - for example when I delete some data - the parent component receives the data and passes it to the child through props but the Table is never updated. So the deleted results still appear on the table.
What is the proper "react/redux" way to generate a refresh of the table ?
Here's some code :
const Results = (props) => {
const router = useRouter()
const { data, error, isError, isLoading, isFetching } = useGetItemsQuery();
if(isLoading) {
return (
<>
<Spinner animation="border" size="sm" role="status" />{' '} Please wait while Loading...
</>
)
}
if(isError) {
return (
<>
<Alert key="warning" variant="warning" style={{marginLeft: "10px"}}>
Warning - There was an error with the request : {error.error}
</Alert>
</>
)
}
const sizePerPageList = [
{
text: '5',
value: 5,
},
];
if (data){
return(
<>
<Card>
<Card.Body>
Traffic results
<TableResults data={data} sizePerPageList={sizePerPageList} />
</Card.Body>
</Card>
</>
)
}
}
export default Results;
And for the second component with the table :
const TableResults = (props) => {
console.log('props - data ', props.data);
const data = React.useMemo(
() => props.data,
[]
)
const columns = React.useMemo(
() => [
{
Header: 'bla bla',
accessor: 'blabla',
}
],
[]
)
const IndeterminateCheckbox = React.forwardRef(
({ indeterminate, ...rest }, ref) => {
const defaultRef = React.useRef()
const resolvedRef = ref || defaultRef
React.useEffect(() => {
resolvedRef.current.indeterminate = indeterminate
}, [resolvedRef, indeterminate])
return (
<>
<input type="checkbox" ref={resolvedRef} {...rest} />
</>
)
}
)
const {
getTableProps,
getTableBodyProps,
headerGroups,
page, // Instead of using 'rows', we'll use page,
// which has only the rows for the active page
// The rest of these things are super handy, too ;)
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
prepareRow,
state: { pageIndex, pageSize, selectedRowIds },
visibleColumns,
preGlobalFilteredRows,
setGlobalFilter,
selectedFlatRows
} = useTable({ columns, data }, useGlobalFilter, useFilters, useSortBy, usePagination, useRowSelect,
hooks => {
hooks.visibleColumns.push(columns => [
// Let's make a column for selection
{
id: 'selection',
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox
Header: ({ getToggleAllPageRowsSelectedProps }) => (
<div>
<IndeterminateCheckbox {...getToggleAllPageRowsSelectedProps()} />
</div>
),
// The cell can use the individual row's getToggleRowSelectedProps method
// to the render a checkbox
Cell: ({ row }) => (
<div>
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
</div>
),
},
...columns,
])
} )
return (
<>
<DeleteItemButton items={selectedFlatRows} />
<BTable {...getTableProps()} striped bordered hover size="sm">
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th
{...column.getHeaderProps(column.getSortByToggleProps())}
>
{column.render('Header')}
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{page.map((row, i) => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return (
<td
{...cell.getCellProps()}
style={{
// padding: '10px',
// border: 'solid 1px gray',
// background: 'papayawhip',
}}
>
{cell.render('Cell')}
</td>
)
})}
</tr>
)
})}
</tbody>
</BTable>
<div className="pagination">
<button onClick={() => gotoPage(0)} disabled={!canPreviousPage}>
{'<<'}
</button>{' '}
<button onClick={() => previousPage()} disabled={!canPreviousPage}>
{'<'}
</button>{' '}
<button onClick={() => nextPage()} disabled={!canNextPage}>
{'>'}
</button>{' '}
<button onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage}>
{'>>'}
</button>{' '}
<span>
Page{' '}
<strong>
{pageIndex + 1} of {pageOptions.length}
</strong>{' '}
</span>
<span>
| Go to page:{' '}
<input
type="number"
defaultValue={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>
</>
)
}
export default TableResults;
The DeleteItemButton will generate a simple RTK query that is functioning very well, and that triggers a refresh of the data from the main component :
deleteItems: builder.mutation({
query(data) {
// send array
let sanitized;
sanitized = keywords.filter(item => item);
const data = {
items: sanitized
}
//console.log('data: ', data);
return {
url: `items`,
method: 'DELETE',
body: data
}
},
invalidatesTags: ['Items']
}),
The app is running under nextJS. Any help appreciated !
Thanks
What is the proper "react/redux" way to generate a refresh of the table?
The correct way to refresh your data is by using the providesTags and invalidatesTags features of RTK query, which you are already doing.
The reason that your table is not refreshing is because you explicitly told it to ignore all changes to props.data and to use the initial value for all subsequent renders. This is obviously not what you intended, but it's what you're doing here:
const data = React.useMemo(
() => props.data,
[]
)
A useMemo with an empty dependency array will only execute once. Generally speaking, all variables which you use inside the useMemo should be included as dependencies. So the dependencies array should be [props.data].
Of course this particular useMemo does not do anything and can be safely deleted. It would make sense to have a useMemo if you were doing some reformatting of the props.data variable and wanted to only execute the reformatting when the value of props.data changes.
const data = React.useMemo(
() => someExpensiveComputation(props.data),
[props.data]
);

how to make InfiniteScroll implementation updated because it update only one time in React table?

import React, { useEffect, useMemo, useState } from 'react' ;
import { useTable , useSortBy } from 'react-table';
import MOCK_DATA from '../MOCK_DATA.json';
import { Columns } from './columns';
import {Checkbox} from './Checkbox';
import InfiniteScroll from 'react-infinite-scroll-component';
export default function DefaultTable() {
const columns = useMemo(() => Columns , [])
const data = useMemo(() => MOCK_DATA , [])
const [items , setItems] = useState(data);
const [hasMore , setHasMore] = useState(true)
const [offset, setOffset] = useState(10);
const fetchMoreData = () => {
// a fake async api call like which sends
// 20 more records in .5 secs
if (items.length >= items.length +1) {
setHasMore( false );
return;
}
setTimeout(() => {
setOffset( offset + 10);
}, 100);
};
const {getTableProps ,
getTableBodyProps ,
headerGroups ,
rows ,
prepareRow,
allColumns,
getToggleHideAllColumnsProps
} = useTable ({
columns ,
data
},
useSortBy
)
return (
<div>
<div>
<Checkbox {...getToggleHideAllColumnsProps()} /> Toggle All
{
allColumns.map(column =>(
<span key={column.id}>
<label>
<input type='checkbox' {...column.getToggleHiddenProps()} />
{column.Header}
</label>
</span>
))
}
</div>
<div
id="scrollableDiv"
style={{
height: 320,
overflow: 'auto',
display: 'flex',
}}
>
<InfiniteScroll
dataLength={rows.length} //This is important field to render the next data
next={fetchMoreData}
hasMore={hasMore}
style={{ display: 'flex', flexDirection: 'column' }}
loader={<h4>Loading more items...</h4>}
scrollableTarget="scrollableDiv"
endMessage={
<p style={{ textAlign: 'center' }}>
<b>Yay! You have seen it all</b>
</p>
}
>
<table {...getTableProps()}>
<thead>
{headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th {...column.getHeaderProps()}>{column.render('Header')}
<span>
{column.isSorted
? column.isSortedDesc
? ' 🔽'
: ' 🔼'
: ''}
</span>
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.slice(0, offset).map((row) => {
// {rows.map((row) => {
prepareRow(row)
return(
<tr {...row.getRowProps()}>
{row.cells.map((cell) => {
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
})}
</tr>
)
})}
</tbody>
</table>
</InfiniteScroll>
</div>
</div>
)
}

Passing Props (img url ) using React-Modal (react js)

I need to pass image url to modal in react js. Like, on click the item from the "imgae attachment", it shows the modal with image for selected item. But it can't show my image data by passing img={item.document}, Here is my code below:
DepositRecord.js
import React, { Component } from "react";
import { Table } from "react-bootstrap";
import { Button, ButtonToolbar } from "react-bootstrap";
import { AddDepositModal } from "./AddDepositModal";
export class DepositRecord extends Component {
constructor(props) {
super(props);
this.state = { deps: [], addModalShow: false };
}
componentDidMount() {
this.refershList();
}
refershList() {
this.setState({
deps: [
{ id: 9, userId: "12", document: "img1_url" },
{ id: 8, userId: "16", document: "img2_url" },
{ id: 6, userId: "13", document: "img3_url" },
{ id: 4, userId: "1", document: "img4_url" },
{ id: 2, userId: "1", document: "img5_url" }
]
});
}
render() {
const { deps } = this.state;
let addModalClose = () => this.setState({ addModalShow: false });
return (
<div>
<h3>Customer's Deposit Record</h3>
<br />
<Table className="mt-4" striped bordered hover size="sm">
<thead>
<tr>
<th>Deposit id</th>
<th>user id</th>
<th>img attachment</th>
</tr>
</thead>
<tbody>
{deps.map((item) => (
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.userId}</td>
<td>
<ButtonToolbar>
<Button
variant="primary"
onClick={() => this.setState({ addModalShow: true })}
>
image attachment
</Button>
<AddDepositModel
show={this.state.addModalShow}
onHide={addModalClose}
img={item.document}
/>
</ButtonToolbar>
</td>
</tr>
))}
</tbody>
</Table>
</div>
);
}
}
export default DepositRecord;
AddDepositModal.js <--the Madal component
import React, { Component } from 'react';
import { Modal, Button, Row, Col, Form } from 'react-bootstrap';
export class AddDepositModal extends Component {
constructor(props) {
super(props);
}
render() {
return (
<Modal
{...this.props}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
Deposit Record
</Modal.Title>
</Modal.Header>
<Modal.Body>
<img src={this.props.img} width={700} height={1100}/>
</Modal.Body>
<Modal.Footer>
<Button variant="danger" onClick={this.props.onHide}>Close</Button>
</Modal.Footer>
</Modal>
);
}
}
export default AddDepositModal;
My Problem: I am not able to pass the image URL to a Modal component and have no better idea solving it in this code.
Please help me and if any including, changes or complete solution for perfect understanding for the requirement would be really great. Many Thanks in Advance!
Hello here's your solution
DepositRecord.js
import React, { useEffect, useState } from "react";
import { Button, ButtonToolbar, Table } from "react-bootstrap";
import AddDepositModal from "./AddDeposiModal";
const DepositRecord = () => {
const [deps, setDeps] = useState([]);
const [visibleModal, setVisibleModal] = useState(false);
const [depImage, setDepImage] = useState(null);
useEffect(() => {
loadDepsHandler();
}, []);
const loadDepsHandler = () => {
const myRequest = new Request("https://randomuser.me/api/", {
method: "GET",
cache: "default",
});
debugger;
fetch(myRequest)
.then((res) => res.json())
.then((data) => {
const { results } = data;
setDeps(results);
})
.catch((err) => console.log(err));
};
const setDepHandler = (id) => {
const dep = deps.find((a) => a.id.value === id);
debugger;
setDepImage(dep.picture.large);
setVisibleModal(true);
};
return (
<div>
<h3>Customer's Deposit Record</h3>
<br />
<Table className="mt-4" striped bordered hover size="sm">
<thead>
<tr>
<th>Deposit id</th>
<th>user name</th>
<th>img attachment</th>
</tr>
</thead>
<tbody>
{deps.map((item) => (
<tr key={item.id.name}>
<td>{item.id.name}</td>
<td>{item.value}</td>
<td>
<ButtonToolbar>
<Button
variant="primary"
onClick={() => setDepHandler(item.id.value)}
>
image attachment
</Button>
</ButtonToolbar>
</td>
</tr>
))}
</tbody>
</Table>
{visibleModal && (
<AddDepositModal
show={visibleModal}
onHide={() => setVisibleModal(false)}
image={depImage}
/>
)}
</div>
);
};
export default DepositRecord;
AddDepositModal.js
import React from "react";
import { Button, Modal } from "react-bootstrap";
const AddDepositModal = ({ show, onHide, image }) => {
return (
<Modal show={show} onHide={onHide}>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
Deposit Record
</Modal.Title>
</Modal.Header>
<Modal.Body>
<img src={image} width={700} height={1100} alt={image} />
</Modal.Body>
<Modal.Footer>
<Button variant="danger" onClick={onHide}>
Close
</Button>
</Modal.Footer>
</Modal>
);
};
export default AddDepositModal;
Async call added. This API is public so it's will take some time to get results
.

getServerSideProps or getStaticProps is not getting called if I use the component as markup in nextjs

I just started with the NextJS. I have created two pages PageA and PageB. Here is the code
PageB
import type { NextPage } from 'next';
import axios from 'axios';
const PageB: NextPage = ({ data = [] }: any) => {
return (
<div>
<table style={{ width: "100%" }}>
<thead>
<tr style={{ width: "100%" }}>
<th style={{ width: "20%" }}>Name</th>
</tr>
</thead>
{/* rows */}
<tbody>
{
data.map((post: any) => {
return <tr key={post._id}>
<td>{post.name}</td>
</tr>;
})
}
</tbody>
</table>
</div>
)
}
export const getServerSideProps = async ({ query }) => {
const myData = await axios.get(`http://localhost:443/api/data`);
return { data: myData.data };
}
export default PageB;
and PageA that will use PageB
import type { NextPage } from 'next';
import axios from 'axios';
import PageB from '../pageb';
const PageA: NextPage = ({ chats }: any) => {
return (
<div>
<table style={{ width: "100%" }}>
<thead>
<tr style={{ width: "100%" }}>
<th style={{ width: "50%" }}>Sender Id</th>
</tr>
</thead>
{/* rows */}
<tbody>
{
chats.map((chat: any) => {
return <tr key={chat._id}>
<td>{chat.sender_id}</td>
</tr>;
})
}
</tbody>
</table>
</div>
<PageB></PageB>
</>
)
}
export const getServerSideProps = async ({ query }) => {
const chats = await axios.get(`http://localhost:443/api/chats`);
// console.log(posts);
return { chats: chats.data };
}
export default PageA;
Now PageB shows the empty list. And if i directly redirect to the /pageb it shows the data.
what is the problem?

reactjs - React Table Pagination appears to be broken

I am new to using React JS. I have been using react-table to create a component that can filter, sort and paginate some sample data from a JSON file.
Here is the link to the tutorial I have been following:
https://www.freakyjolly.com/react-table-tutorial/#.YBfqqZP7SL4
Here is what I am seeing at the moment, the pagination appears to be broken, I am seeing all of the data appear (1000 rows). I am trying to have around 5-10 records showing at a time.
Here is the App.js code.
import React from 'react';
import logo from './logo.svg';
import './App.css';
import FilterTableComponent from './components/filter.pagination.sorting';
function App() {
return (
<div className="App">
<h3>Filter Table using <code>react-table</code></h3>
<FilterTableComponent />
</div>
);
}
export default App;
Here is the filter.paginate.sorting.js code
import React from "react";
import { useTable, useSortBy, usePagination, useFilters, useGlobalFilter, useAsyncDebounce } from 'react-table';
import 'bootstrap/dist/css/bootstrap.min.css';
import JSONDATA from './MOCK_DATA.json';
// Define a default UI for filtering
function GlobalFilter({
preGlobalFilteredRows,
globalFilter,
setGlobalFilter,
}) {
const count = preGlobalFilteredRows.length
const [value, setValue] = React.useState(globalFilter)
const onChange = useAsyncDebounce(value => {
setGlobalFilter(value || undefined)
}, 200)
return (
<span>
Search:{' '}
<input
className="form-control"
value={value || ""}
onChange={e => {
setValue(e.target.value);
onChange(e.target.value);
}}
placeholder={`${count} records...`}
/>
</span>
)
}
function DefaultColumnFilter({
column: { filterValue, preFilteredRows, setFilter },
}) {
const count = preFilteredRows.length
return (
<input
className="form-control"
value={filterValue || ''}
onChange={e => {
setFilter(e.target.value || undefined)
}}
placeholder={`Search ${count} records...`}
/>
)
}
function Table({ columns, data }) {
const defaultColumn = React.useMemo(
() => ({
// Default Filter UI
Filter: DefaultColumnFilter,
}),
[]
)
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
rows,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
state,
state: { pageIndex, pageSize },
preGlobalFilteredRows,
setGlobalFilter,
} = useTable(
{
columns,
data,
defaultColumn,
initialState: { pageIndex: 0, pageSize: 10 }
},
useFilters,
useGlobalFilter,
useSortBy,
usePagination
)
return (
<div>
<ul className="pagination">
<li className="page-item" onClick={() => gotoPage(0)} disabled={!canPreviousPage}>
<a className="page-link">First</a>
</li>
<li className="page-item" onClick={() => previousPage()} disabled={!canPreviousPage}>
<a className="page-link">{'<'}</a>
</li>
<li className="page-item" onClick={() => nextPage()} disabled={!canNextPage}>
<a className="page-link">{'>'}</a>
</li>
<li className="page-item" onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage}>
<a className="page-link">Last</a>
</li>
<li>
<a className="page-link">
Page{' '}
<strong>
{pageIndex + 1} of {pageOptions.length}
</strong>{' '}
</a>
</li>
<li>
<a className="page-link">
<input
className="form-control"
type="number"
defaultValue={pageIndex + 1}
onChange={e => {
const page = e.target.value ? Number(e.target.value) - 1 : 0
gotoPage(page)
}}
style={{ width: '100px', height: '20px' }}
/>
</a>
</li>{' '}
<select
className="form-control"
value={pageSize}
onChange={e => {
setPageSize(Number(e.target.value))
}}
style={{ width: '120px', height: '38px' }}
>
{[5, 10, 20, 30, 40, 50].map(pageSize => (
<option key={pageSize} value={pageSize}>
Show {pageSize}
</option>
))}
</select>
</ul>
<GlobalFilter
preGlobalFilteredRows={preGlobalFilteredRows}
globalFilter={state.globalFilter}
setGlobalFilter={setGlobalFilter}
/>
<pre>
<code>
{JSON.stringify(
{
pageIndex,
pageSize,
pageCount,
canNextPage,
canPreviousPage,
},
null,
2
)}
</code>
</pre>
<table className="table" {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th {...column.getHeaderProps(column.getSortByToggleProps())}>
{column.render('Header')}
{/* Render the columns filter UI */}
<div>{column.canFilter ? column.render('Filter') : null}</div>
<span>
{column.isSorted
? column.isSortedDesc
? ' '
: ' '
: ''}
</span>
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map((row, i) => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
})}
</tr>
)
})}
</tbody>
</table>
<br />
<div>Showing the first 20 results of {rows.length} rows</div>
<div>
<pre>
<code>{JSON.stringify(state.filters, null, 2)}</code>
</pre>
</div>
</div>
)
}
function FilterTableComponent() {
const columns = React.useMemo(
() => [
{
Header: 'Name',
columns: [
{
Header: 'WIP_ID',
accessor: 'WIP_ID',
},
{
Header: 'PRODUCT_SERIAL_NUMBER',
accessor: 'PRODUCT_SERIAL_NUMBER'
},
],
},
{
Header: 'Info',
columns: [
{
Header: 'DATE',
accessor: 'DATE'
},
{
Header: 'BUCKET_NAME',
accessor: 'BUCKET_NAME'
},
{
Header: 'CREATED_TS',
accessor: 'CREATED_TS'
},
{
Header: 'FILE_NAME',
accessor: 'FILE_NAME'
},
],
},
],
[]
)
const data = JSONDATA
return (
<Table columns={columns} data={data} />
)
}
export default FilterTableComponent;
Here is a sample of what the JSON file looks like. Named - MOCK_DATA.json
[{"WIP_ID":"56c97f3e-1c3f-4463-beb2-1af58ebe0db0","PRODUCT_SERIAL_NUMBER":"eab8304c-43e2-4f70-a23a-2db75bf2ce50","DATE":"29/06/2020","BUCKET_NAME":"Bytecard","CREATED_TS":"03/10/2020","FILE_NAME":"elit_proin.tiff"},
{"WIP_ID":"b358a03b-fee6-4957-9017-1de3d9846264","PRODUCT_SERIAL_NUMBER":"b974e89e-9bf9-4329-bc13-1afc3bdd52e0","DATE":"20/12/2020","BUCKET_NAME":"Vagram","CREATED_TS":"25/11/2020","FILE_NAME":"condimentum_id_luctus.mov"},
{"WIP_ID":"9fab6d70-72bc-40ae-a99f-5ae31dc47aec","PRODUCT_SERIAL_NUMBER":"8f9f70ce-b940-486b-a003-5c9db031e54e","DATE":"15/02/2020","BUCKET_NAME":"Domainer","CREATED_TS":"06/05/2020","FILE_NAME":"interdum_in_ante.tiff"},
{"WIP_ID":"5bb40cfb-99dc-413a-8b5f-0b6612e45d34","PRODUCT_SERIAL_NUMBER":"3bab0d2b-5464-4c5d-b1c8-0ba6b32e60fa","DATE":"14/03/2020","BUCKET_NAME":"Lotlux","CREATED_TS":"11/05/2020","FILE_NAME":"diam_nam_tristique.avi"},
{"WIP_ID":"95ae9754-e288-4ceb-b7cf-1b27892e7ace","PRODUCT_SERIAL_NUMBER":"1280dfb1-152d-44fd-aed7-4de8b8b573a6","DATE":"04/04/2020","BUCKET_NAME":"Gembucket","CREATED_TS":"14/10/2020","FILE_NAME":"vehicula.pdf"},
I think you need to change this in your tbody
{rows.map((row,i) =>
to
{page.map((row,i) =>

Categories