Skip to content
Permalink
Browse files

fix(use-pagination): better controlled/manual use-pagination

  • Loading branch information...
tannerlinsley committed Aug 7, 2019
1 parent 4f01c32 commit a667b7cb1397c28b410b6ffb23f6aa37d33682e8
Showing with 10,816 additions and 36 deletions.
  1. +12 −9 README.md
  2. 0 examples/{basic-client-side → basic}/.babelrc
  3. 0 examples/{basic-client-side → basic}/.env
  4. 0 examples/{basic-client-side → basic}/.eslintrc
  5. 0 examples/{basic-client-side → basic}/.gitignore
  6. 0 examples/{basic-client-side → basic}/.rescriptsrc.js
  7. 0 examples/{basic-client-side → basic}/README.md
  8. 0 examples/{basic-client-side → basic}/package.json
  9. BIN examples/{basic-client-side → basic}/public/favicon.ico
  10. 0 examples/{basic-client-side → basic}/public/index.html
  11. 0 examples/{basic-client-side → basic}/public/manifest.json
  12. 0 examples/{basic-client-side → basic}/src/App.js
  13. 0 examples/{basic-client-side → basic}/src/App.test.js
  14. 0 examples/{basic-client-side → basic}/src/index.css
  15. 0 examples/{basic-client-side → basic}/src/index.js
  16. 0 examples/{basic-client-side → basic}/src/makeData.js
  17. 0 examples/{basic-client-side → basic}/src/serviceWorker.js
  18. 0 examples/{basic-client-side → basic}/yarn.lock
  19. 0 examples/{expanding-client-side → expanding}/.babelrc
  20. 0 examples/{expanding-client-side → expanding}/.env
  21. 0 examples/{expanding-client-side → expanding}/.eslintrc
  22. 0 examples/{expanding-client-side → expanding}/.gitignore
  23. 0 examples/{expanding-client-side → expanding}/.rescriptsrc.js
  24. 0 examples/{expanding-client-side → expanding}/README.md
  25. 0 examples/{expanding-client-side → expanding}/package.json
  26. BIN examples/{expanding-client-side → expanding}/public/favicon.ico
  27. 0 examples/{expanding-client-side → expanding}/public/index.html
  28. 0 examples/{expanding-client-side → expanding}/public/manifest.json
  29. 0 examples/{expanding-client-side → expanding}/src/App.js
  30. 0 examples/{expanding-client-side → expanding}/src/App.test.js
  31. 0 examples/{expanding-client-side → expanding}/src/index.css
  32. 0 examples/{expanding-client-side → expanding}/src/index.js
  33. 0 examples/{expanding-client-side → expanding}/src/makeData.js
  34. 0 examples/{expanding-client-side → expanding}/src/serviceWorker.js
  35. 0 examples/{expanding-client-side → expanding}/yarn.lock
  36. 0 examples/{filtering-client-side → filtering}/.babelrc
  37. 0 examples/{filtering-client-side → filtering}/.env
  38. 0 examples/{filtering-client-side → filtering}/.eslintrc
  39. 0 examples/{filtering-client-side → filtering}/.gitignore
  40. 0 examples/{filtering-client-side → filtering}/.rescriptsrc.js
  41. 0 examples/{filtering-client-side → filtering}/README.md
  42. 0 examples/{filtering-client-side → filtering}/package.json
  43. BIN examples/{filtering-client-side → filtering}/public/favicon.ico
  44. 0 examples/{filtering-client-side → filtering}/public/index.html
  45. 0 examples/{filtering-client-side → filtering}/public/manifest.json
  46. 0 examples/{filtering-client-side → filtering}/src/App.js
  47. 0 examples/{filtering-client-side → filtering}/src/App.test.js
  48. 0 examples/{filtering-client-side → filtering}/src/index.css
  49. 0 examples/{filtering-client-side → filtering}/src/index.js
  50. 0 examples/{filtering-client-side → filtering}/src/makeData.js
  51. 0 examples/{filtering-client-side → filtering}/src/serviceWorker.js
  52. 0 examples/{filtering-client-side → filtering}/yarn.lock
  53. 0 examples/{grouping-client-side → grouping}/.babelrc
  54. 0 examples/{grouping-client-side → grouping}/.env
  55. 0 examples/{grouping-client-side → grouping}/.eslintrc
  56. 0 examples/{grouping-client-side → grouping}/.gitignore
  57. 0 examples/{grouping-client-side → grouping}/.rescriptsrc.js
  58. 0 examples/{grouping-client-side → grouping}/README.md
  59. 0 examples/{grouping-client-side → grouping}/package.json
  60. BIN examples/{grouping-client-side → grouping}/public/favicon.ico
  61. 0 examples/{grouping-client-side → grouping}/public/index.html
  62. 0 examples/{grouping-client-side → grouping}/public/manifest.json
  63. 0 examples/{grouping-client-side → grouping}/src/App.js
  64. 0 examples/{grouping-client-side → grouping}/src/App.test.js
  65. 0 examples/{grouping-client-side → grouping}/src/index.css
  66. 0 examples/{grouping-client-side → grouping}/src/index.js
  67. 0 examples/{grouping-client-side → grouping}/src/makeData.js
  68. 0 examples/{grouping-client-side → grouping}/src/serviceWorker.js
  69. 0 examples/{grouping-client-side → grouping}/yarn.lock
  70. 0 examples/{pagination-client-side → pagination-controlled}/.babelrc
  71. 0 examples/{pagination-client-side → pagination-controlled}/.env
  72. 0 examples/{pagination-client-side → pagination-controlled}/.eslintrc
  73. 0 examples/{pagination-client-side → pagination-controlled}/.gitignore
  74. 0 examples/{pagination-client-side → pagination-controlled}/.rescriptsrc.js
  75. 0 examples/{pagination-client-side → pagination-controlled}/README.md
  76. 0 examples/{pagination-client-side → pagination-controlled}/package.json
  77. BIN examples/{pagination-client-side → pagination-controlled}/public/favicon.ico
  78. 0 examples/{pagination-client-side → pagination-controlled}/public/index.html
  79. 0 examples/{pagination-client-side → pagination-controlled}/public/manifest.json
  80. 0 examples/{pagination-client-side → pagination-controlled}/sandbox.config.json
  81. +276 −0 examples/pagination-controlled/src/App.js
  82. 0 examples/{pagination-client-side → pagination-controlled}/src/App.test.js
  83. 0 examples/{pagination-client-side → pagination-controlled}/src/index.css
  84. 0 examples/{pagination-client-side → pagination-controlled}/src/index.js
  85. 0 examples/{pagination-client-side → pagination-controlled}/src/makeData.js
  86. 0 examples/{pagination-client-side → pagination-controlled}/src/serviceWorker.js
  87. 0 examples/{pagination-client-side → pagination-controlled}/yarn.lock
  88. 0 examples/{row-selection-client-side → pagination}/.babelrc
  89. 0 examples/{row-selection-client-side → pagination}/.env
  90. 0 examples/{row-selection-client-side → pagination}/.eslintrc
  91. 0 examples/{row-selection-client-side → pagination}/.gitignore
  92. 0 examples/{row-selection-client-side → pagination}/.rescriptsrc.js
  93. 0 examples/{row-selection-client-side → pagination}/README.md
  94. 0 examples/{row-selection-client-side → pagination}/package.json
  95. BIN examples/{row-selection-client-side → pagination}/public/favicon.ico
  96. 0 examples/{row-selection-client-side → pagination}/public/index.html
  97. 0 examples/{row-selection-client-side → pagination}/public/manifest.json
  98. +3 −0 examples/pagination/sandbox.config.json
  99. 0 examples/{pagination-client-side → pagination}/src/App.js
  100. 0 examples/{row-selection-client-side → pagination}/src/App.test.js
  101. 0 examples/{row-selection-client-side → pagination}/src/index.css
  102. 0 examples/{row-selection-client-side → pagination}/src/index.js
  103. 0 examples/{row-selection-client-side → pagination}/src/makeData.js
  104. 0 examples/{row-selection-client-side → pagination}/src/serviceWorker.js
  105. 0 examples/{row-selection-client-side → pagination}/yarn.lock
  106. 0 examples/{sorting-client-side → row-selection}/.babelrc
  107. 0 examples/{sorting-client-side → row-selection}/.env
  108. 0 examples/{sorting-client-side → row-selection}/.eslintrc
  109. 0 examples/{sorting-client-side → row-selection}/.gitignore
  110. 0 examples/{sorting-client-side → row-selection}/.rescriptsrc.js
  111. 0 examples/{sorting-client-side → row-selection}/README.md
  112. 0 examples/{sorting-client-side → row-selection}/package.json
  113. BIN examples/{sorting-client-side → row-selection}/public/favicon.ico
  114. 0 examples/{sorting-client-side → row-selection}/public/index.html
  115. 0 examples/{sorting-client-side → row-selection}/public/manifest.json
  116. 0 examples/{row-selection-client-side → row-selection}/src/App.js
  117. +9 −0 examples/row-selection/src/App.test.js
  118. 0 examples/{sorting-client-side → row-selection}/src/index.css
  119. +12 −0 examples/row-selection/src/index.js
  120. 0 examples/{sorting-client-side → row-selection}/src/makeData.js
  121. +135 −0 examples/row-selection/src/serviceWorker.js
  122. 0 examples/{sorting-client-side → row-selection}/yarn.lock
  123. +4 −0 examples/sorting/.babelrc
  124. +1 −0 examples/sorting/.env
  125. +7 −0 examples/sorting/.eslintrc
  126. +23 −0 examples/sorting/.gitignore
  127. +29 −0 examples/sorting/.rescriptsrc.js
  128. +6 −0 examples/sorting/README.md
  129. +35 −0 examples/sorting/package.json
  130. BIN examples/sorting/public/favicon.ico
  131. +38 −0 examples/sorting/public/index.html
  132. +15 −0 examples/sorting/public/manifest.json
  133. 0 examples/{sorting-client-side → sorting}/src/App.js
  134. 0 examples/{sorting-client-side → sorting}/src/App.test.js
  135. +13 −0 examples/sorting/src/index.css
  136. 0 examples/{sorting-client-side → sorting}/src/index.js
  137. +40 −0 examples/sorting/src/makeData.js
  138. 0 examples/{sorting-client-side → sorting}/src/serviceWorker.js
  139. +10,145 −0 examples/sorting/yarn.lock
  140. +13 −27 src/plugin-hooks/usePagination.js
@@ -182,15 +182,18 @@ import {
# Examples
- [Basic - Client Side](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/basic-client-side)
- [Sorting - Client Side](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/sorting-client-side)
- [Filtering - Client Side](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/filtering-client-side)
- [Grouping - Client Side](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/grouping-client-side)
- [Pagination - Client Side](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/pagination-client-side)
- [Row Selection - Client Side](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/row-selection-client-side)
- [Expanding - Client Side](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/expanding-client-side)
- [Sub Components](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/sub-components)
- [Editable Data](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/editable-cells)
- Simple
- [Basic](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/basic)
- [Sorting](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/sorting)
- [Filtering](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/filtering)
- [Grouping](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/grouping)
- [Pagination](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/pagination)
- [Row Selection](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/row-selection)
- [Expanding](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/expanding)
- [Sub Components](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/sub-components)
- [Editable Data](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/editable-cells)
- Controlled
- [Pagination (Controlled)](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/pagination-controlled)
# Concepts
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,276 @@
import React from 'react'
import styled from 'styled-components'
import { useTable, useTableState, usePagination } from 'react-table'

import makeData from './makeData'

const Styles = styled.div`
padding: 1rem;
table {
border-spacing: 0;
border: 1px solid black;
tr {
:last-child {
td {
border-bottom: 0;
}
}
}
th,
td {
margin: 0;
padding: 0.5rem;
border-bottom: 1px solid black;
border-right: 1px solid black;
:last-child {
border-right: 0;
}
}
}
.pagination {
padding: 0.5rem;
}
`

// Let's add a fetchData method to our Table component that will be used to fetch
// new data when pagination state changes
// We can also add a loading state to let our table know it's loading new data
function Table({
columns,
data,
fetchData,
loading,
pageCount: controlledPageCount,
}) {
// Use useTableState to hoist the state (and state updater) out of the table and control it
const tableState = useTableState({ pageIndex: 0 })

// Now we can get our table state from the hoisted table state tuple
const [{ pageIndex, pageSize }] = tableState

// Listen for changes in pagination and use the state to fetch our new data
React.useEffect(
() => {
fetchData({ pageIndex, pageSize })
},
[fetchData, pageIndex, pageSize]
)

const {
getTableProps,
headerGroups,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
} = useTable(
{
columns,
data,
state: tableState, // Pass our hoisted table state
manualPagination: true, // Tell the usePagination
// hook that we'll handle our own data fetching
// This means we'll also have to provide our own
// pageCount.
pageCount: controlledPageCount,
},
usePagination
)

// Render the UI for your table
return (
<>
<pre>
<code>
{JSON.stringify(
{
pageIndex,
pageSize,
pageCount,
canNextPage,
canPreviousPage,
},
null,
2
)}
</code>
</pre>
<table {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th {...column.getHeaderProps()}>{column.render('Header')}</th>
))}
</tr>
))}
</thead>
<tbody>
{page.map(
(row, i) =>
prepareRow(row) || (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return (
<td {...cell.getCellProps()}>{cell.render('Cell')}</td>
)
})}
</tr>
)
)}
{loading ? (
// Use our custom loading state to show a loading indicator
<tr>
<td>Loading...</td>
</tr>
) : null}
</tbody>
</table>
{/*
Pagination can be built however you'd like.
This is just a very basic UI implementation:
*/}
<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>
</>
)
}

// Let's simulate a large dataset on the server (outside of our component)
const serverData = makeData(10000)

function App() {
const columns = React.useMemo(
() => [
{
Header: 'Name',
columns: [
{
Header: 'First Name',
accessor: 'firstName',
},
{
Header: 'Last Name',
accessor: 'lastName',
},
],
},
{
Header: 'Info',
columns: [
{
Header: 'Age',
accessor: 'age',
},
{
Header: 'Visits',
accessor: 'visits',
},
{
Header: 'Status',
accessor: 'status',
},
{
Header: 'Profile Progress',
accessor: 'progress',
},
],
},
],
[]
)

// We'll start our table without any data
const [data, setData] = React.useState([])
const [loading, setLoading] = React.useState(false)
const [pageCount, setPageCount] = React.useState(0)

const fetchData = React.useCallback(({ pageSize, pageIndex }) => {
// This will get called when the table needs new data
// You could fetch your data from literally anywhere,
// even a server. But for this example, we'll just fake it.

// Set the loading state
setLoading(true)

// We'll even set a delay to simulate a server here
setTimeout(() => {
const startRow = pageSize * pageIndex
const endRow = startRow + pageSize
setData(serverData.slice(startRow, endRow))

// Your server could send back total page count.
// For now we'll just fake it, too
setPageCount(Math.ceil(serverData.length / pageSize))

setLoading(false)
}, 1000)
}, [])

return (
<Styles>
<Table
columns={columns}
data={data}
fetchData={fetchData}
loading={loading}
pageCount={pageCount}
/>
</Styles>
)
}

export default App
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,3 @@
{
"infiniteLoopProtection": false
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.