'fetch from api that I send requested in react-table
I will need a server-side table so after I saw react-table
got 9k+ stars on github then decided to use it. I'm trying to build a React-Table which can make polling to a remote server every requested data to fetch newest data. In the example I use jsonplaceholder. requestedData
func should get the data by pageSize
and pageIndex
(https://jsonplaceholder.typicode.com/posts?_start={pageIndex will come here}&_limit={pageSize will come here}
) and return the sorted and filtered rows.
How can I do that?
Below I wrote some code:
//Table.js
import React, { useState, useEffect } from 'react';
import { useTable, useFilters, useSortBy, usePagination } from 'react-table';
export default function Table({ columns, data, pages, onFetchData, loading, pageCount: controlledPageCount, error }) {
const [ filterInput, setFilterInput ] = useState('');
// Use the state and functions returned from useTable to build your UI
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
setFilter,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
// Get the state from the instance
state: { pageIndex, pageSize }
} = useTable(
//useTable is the primary hook used to build a React Table
{
columns,
data,
initialState: { pageIndex: 0 },
manualPagination: true,
pageCount: controlledPageCount
},
useFilters, //useFilters is the hook that implements row filtering
useSortBy,
usePagination
);
// Listen for changes in pagination and use the state to fetch our new data
useEffect(
() => {
onFetchData({ pageIndex, pageSize });
},
[ onFetchData, pageIndex, pageSize ]
);
const handleFilterChange = (e) => {
const value = e.target.value || undefined;
setFilter('title', value);
setFilterInput(value);
};
// Render the UI for your table
return (
<React.Fragment>
<pre>
<code>
{JSON.stringify(
{
pageIndex,
pageSize,
pageCount,
canNextPage,
canPreviousPage,
filterInput,
error,
//data,
onFetchData
},
null,
2
)}
</code>
</pre>
<input value={filterInput} onChange={handleFilterChange} placeholder={'Search name'} />
<table {...getTableProps()}>
<thead>
{headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th
{...column.getHeaderProps(column.getSortByToggleProps())}
className={column.isSorted ? column.isSortedDesc ? 'sort-desc' : 'sort-asc' : ''}
>
{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()}>{cell.render('Cell')}</td>;
})}
</tr>
);
})}
<tr>
{loading ? (
// Use our custom loading state to show a loading indicator
<td colSpan='10000'>Loading...</td>
) : (
<td colSpan='10000'>
Showing {page.length} of ~{controlledPageCount * pageSize} results
</td>
)}
</tr>
</tbody>
</table>
<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>
</React.Fragment>
);
}
//App.js
import React, { useMemo, useState, useEffect } from 'react';
import Table from './Table';
import './App.css';
import _ from 'lodash';
import axios from 'axios';
function App() {
const columns = useMemo(
() => [
{
Header: 'Information',
columns: [
{
Header: 'Key',
accessor: 'id'
},
{
Header: 'Header',
accessor: 'title'
},
{
Header: 'Content',
accessor: 'body'
}
]
}
],
[]
);
const [ data, setData ] = useState([]);
const [ loading, setLoading ] = useState(false);
const [ pageCount, setPageCount ] = useState(0);
const [ error, setError ] = useState(null);
useEffect(() => {
(async () => {
const result = await axios('https://jsonplaceholder.typicode.com/posts?_start=0&_limit=5');
setData(result.data);
})();
}, []);
const requestData = (pageSize, pageIndex, sorted, filtered) => {
// Set the loading state
setLoading(true);
return new Promise((resolve, reject) => {
const startRow = pageSize * pageIndex;
axios
.get(`https://jsonplaceholder.typicode.com/posts?_start=${startRow}&_limit=${pageSize}`)
.then((response) => {
let filteredData = response.data;
if (filtered.length) {
filteredData = filtered.reduce((filteredSoFar, nextFilter) => {
return filteredSoFar.filter((row) => {
return (row[nextFilter.id] + '').includes(nextFilter.value);
});
}, filteredData);
}
const sortedData = _.orderBy(
filteredData,
sorted.map((sort) => {
return (row) => {
if (row[sort.id] === null || row[sort.id] === undefined) {
return -Infinity;
}
return typeof row[sort.id] === 'string' ? row[sort.id].toLowerCase() : row[sort.id];
};
}),
sorted.map((d) => (d.desc ? 'desc' : 'asc'))
);
const res = {
rows: sortedData,
pages: Math.ceil(response.data.count / pageSize)
};
// setSortedData(res.rows);
setPageCount(res.pages);
setTimeout(() => resolve(res), 500);
setLoading(false);
})
.catch((error) => {
// setError(error);
console.log('error', error);
});
});
};
const fetchData = (state, instance) => {
setLoading(true);
requestData(state.pageSize, state.page, state.sorted, state.filtered)
.then((res) => {
setData(res.data);
setPageCount(res.pages);
setLoading(false);
})
.catch((err) => {
setError(err);
setLoading(false);
});
};
return (
<div className='App'>
<Table
columns={columns}
data={data}
pages={pageCount}
onFetchData={fetchData}
loading={loading}
pageCount={pageCount}
error={error}
/>
</div>
);
}
export default App;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|