-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
28 changed files
with
922 additions
and
114 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"env": { | ||
"test": { "presets": ["@babel/preset-env", "@babel/preset-react"] } | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
cjs/ | ||
es/ | ||
umd.js | ||
umd/ | ||
coverage/ | ||
examples/umd.js |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
node_modules/ | ||
cjs/ | ||
es/ | ||
umd/ | ||
coverage/ | ||
|
||
.eslintcache | ||
package-lock.json | ||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
examples/ |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# token-pagination-hooks | ||
|
||
React Hooks library to use classic pagination in the frontend with a token-based paginatiom backend | ||
|
||
## Setup | ||
|
||
`npm i token-pagination-hooks` | ||
|
||
## Quickstart | ||
|
||
The API you're using | ||
|
||
- accepts a `pageToken` query string parameter to do pagination | ||
- returns data in the format: | ||
|
||
```json | ||
{ | ||
"data": [...], | ||
"nextPage": "some opaque string" | ||
} | ||
``` | ||
|
||
Assuming you're using a library like [axios-hooks](https://github.com/simoneb/axios-hooks/) to interact with the API: | ||
|
||
```js | ||
import React, { useState } from 'react' | ||
import useAxios from 'axios-hooks' | ||
import useTokenPagination from 'token-pagination-hooks' | ||
|
||
function Pagination() { | ||
const [pageNumber, setPageNumber] = useState(1) | ||
const { currentToken, useUpdateToken } = useTokenPagination(pageNumber) | ||
const [{ data }] = useAxios({ url: '/api', params: { pageToken: currentToken }) | ||
} | ||
``` |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"env": { | ||
"browser": true, | ||
"node": true | ||
}, | ||
"parserOptions": { "sourceType": "script" }, | ||
"globals": { | ||
"React": true, | ||
"PropTypes": true, | ||
"useTokenPagination": true, | ||
"Output": true, | ||
"Source": true, | ||
"SimpleDeclarative": true, | ||
"SimpleImperative": true, | ||
"InternalState": true | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
const choices = [SimpleDeclarative, SimpleImperative, InternalState].reduce( | ||
(acc, c) => ({ ...acc, [c.name]: c }), | ||
{} | ||
) | ||
|
||
function Example() { | ||
const [choice, setChoice] = React.useState(SimpleDeclarative.name) | ||
|
||
const Component = choices[choice] | ||
|
||
return ( | ||
<div> | ||
<select value={choice} onChange={e => setChoice(e.target.value)}> | ||
{Object.keys(choices).map(c => ( | ||
<option key={c}>{c}</option> | ||
))} | ||
</select> | ||
<div style={{ display: 'flex' }}> | ||
<div> | ||
<Component /> | ||
</div> | ||
<div style={{ marginLeft: '3rem' }}> | ||
<Source fileName={choice} /> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
Example.propTypes = {} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
const { useState, useEffect } = React | ||
|
||
function InternalState() { | ||
const { | ||
currentToken, | ||
useUpdateToken, | ||
changePageNumber, | ||
changePageSize, | ||
pageNumber, | ||
pageSize, | ||
} = useTokenPagination({ defaultPageNumber: 1, defaultPageSize: 5 }) | ||
|
||
const [data, setData] = useState() | ||
|
||
useEffect(() => { | ||
async function fetchData() { | ||
const params = new URLSearchParams({ pageSize }) | ||
|
||
if (currentToken) { | ||
params.append('pageToken', currentToken) | ||
} | ||
|
||
const res = await fetch(`/api?${params.toString()}`) | ||
const data = await res.json() | ||
|
||
setData(data) | ||
} | ||
|
||
fetchData() | ||
}, [pageSize, currentToken]) | ||
|
||
useUpdateToken(data?.nextPage) | ||
|
||
function previousPage() { | ||
changePageNumber(n => n - 1) | ||
} | ||
function nextPage() { | ||
changePageNumber(n => n + 1) | ||
} | ||
function handleChangePageSize(e) { | ||
changePageSize(+e.target.value) | ||
} | ||
|
||
return ( | ||
<Output | ||
data={data} | ||
pageNumber={pageNumber} | ||
pageSize={pageSize} | ||
changePageSize={handleChangePageSize} | ||
previousPage={previousPage} | ||
nextPage={nextPage} | ||
/> | ||
) | ||
} | ||
|
||
InternalState.propTypes = {} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
const T = PropTypes | ||
|
||
function Output({ | ||
data, | ||
pageNumber, | ||
pageSize, | ||
changePageSize, | ||
previousPage, | ||
nextPage, | ||
}) { | ||
return ( | ||
<> | ||
<pre>{JSON.stringify(data, null, 2)}</pre> | ||
<div> | ||
<select value={pageSize} onChange={changePageSize}> | ||
<option value={3}>3</option> | ||
<option value={5}>5</option> | ||
<option value={12}>12</option> | ||
</select> | ||
{' '} | ||
|
||
<button disabled={pageNumber <= 1} onClick={previousPage}> | ||
<< | ||
</button> | ||
{' '} | ||
{pageNumber} | ||
{' '} | ||
<button disabled={!data?.nextPage} onClick={nextPage}> | ||
>> | ||
</button> | ||
</div> | ||
</> | ||
) | ||
} | ||
|
||
Output.propTypes = { | ||
data: T.shape({ | ||
nextPage: T.any, | ||
}), | ||
pageNumber: T.number.isRequired, | ||
pageSize: T.number.isRequired, | ||
changePageSize: T.func.isRequired, | ||
previousPage: T.func.isRequired, | ||
nextPage: T.func.isRequired, | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
const { useState, useEffect } = React | ||
|
||
function SimpleDeclarative() { | ||
const [{ pageNumber, pageSize }, setPagination] = useState({ | ||
pageNumber: 1, | ||
pageSize: 3, | ||
}) | ||
const { currentToken, useUpdateToken } = useTokenPagination(pageNumber) | ||
|
||
const [data, setData] = useState() | ||
|
||
useEffect(() => { | ||
async function fetchData() { | ||
const params = new URLSearchParams({ pageSize }) | ||
|
||
if (currentToken) { | ||
params.append('pageToken', currentToken) | ||
} | ||
|
||
const res = await fetch(`/api?${params.toString()}`) | ||
const data = await res.json() | ||
|
||
setData(data) | ||
} | ||
|
||
fetchData() | ||
}, [pageSize, currentToken]) | ||
|
||
useUpdateToken(data?.nextPage) | ||
|
||
function previousPage() { | ||
setPagination(s => ({ ...s, pageNumber: pageNumber - 1 })) | ||
} | ||
function nextPage() { | ||
setPagination(s => ({ ...s, pageNumber: pageNumber + 1 })) | ||
} | ||
function changePageSize(e) { | ||
setPagination({ pageSize: e.target.value, pageNumber: 1 }) | ||
} | ||
|
||
return ( | ||
<Output | ||
data={data} | ||
pageNumber={pageNumber} | ||
pageSize={pageSize} | ||
changePageSize={changePageSize} | ||
previousPage={previousPage} | ||
nextPage={nextPage} | ||
/> | ||
) | ||
} | ||
|
||
SimpleDeclarative.propTypes = {} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
const { useState, useEffect } = React | ||
|
||
function SimpleImperative() { | ||
const [{ pageNumber, pageSize }, setPagination] = useState({ | ||
pageNumber: 1, | ||
pageSize: 3, | ||
}) | ||
const { currentToken, updateToken } = useTokenPagination(pageNumber) | ||
|
||
const [data, setData] = useState() | ||
|
||
useEffect(() => { | ||
async function fetchData() { | ||
const params = new URLSearchParams({ pageSize }) | ||
|
||
if (currentToken) { | ||
params.append('pageToken', currentToken) | ||
} | ||
|
||
const res = await fetch(`/api?${params.toString()}`) | ||
const data = await res.json() | ||
|
||
updateToken(data.nextPage) | ||
|
||
setData(data) | ||
} | ||
|
||
fetchData() | ||
}, [pageSize, currentToken, updateToken]) | ||
|
||
function previousPage() { | ||
setPagination(s => ({ ...s, pageNumber: pageNumber - 1 })) | ||
} | ||
function nextPage() { | ||
setPagination(s => ({ ...s, pageNumber: pageNumber + 1 })) | ||
} | ||
function changePageSize(e) { | ||
setPagination({ pageSize: e.target.value, pageNumber: 1 }) | ||
} | ||
|
||
return ( | ||
<Output | ||
data={data} | ||
pageNumber={pageNumber} | ||
pageSize={pageSize} | ||
changePageSize={changePageSize} | ||
previousPage={previousPage} | ||
nextPage={nextPage} | ||
/> | ||
) | ||
} | ||
|
||
SimpleImperative.propTypes = {} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
const { useState, useEffect } = React | ||
const T = PropTypes | ||
|
||
function Source({ fileName }) { | ||
const [source, setSource] = useState() | ||
|
||
useEffect(() => { | ||
async function fetchSource() { | ||
const res = await fetch(`/components/${fileName}.js`) | ||
|
||
setSource(await res.text()) | ||
} | ||
|
||
fetchSource() | ||
}, [fileName]) | ||
|
||
return ( | ||
<div> | ||
<h3>{fileName} source code</h3> | ||
<pre> | ||
<code>{source}</code> | ||
</pre> | ||
</div> | ||
) | ||
} | ||
|
||
Source.propTypes = { | ||
fileName: T.string.isRequired, | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<title>Example</title> | ||
<script src="https://unpkg.com/react@17/umd/react.development.js"></script> | ||
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script> | ||
<script src="https://unpkg.com/prop-types@15/prop-types.js"></script> | ||
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> | ||
<script src="umd.js"></script> | ||
<script type="text/babel" src="components/Output.js"></script> | ||
<script type="text/babel" src="components/Source.js"></script> | ||
<script type="text/babel" src="components/SimpleDeclarative.js"></script> | ||
<script type="text/babel" src="components/SimpleImperative.js"></script> | ||
<script type="text/babel" src="components/InternalState.js"></script> | ||
<script type="text/babel" src="components/Example.js"></script> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script type="text/babel"> | ||
ReactDOM.render(<Example />, document.getElementById('root')) | ||
</script> | ||
</body> | ||
</html> |
Oops, something went wrong.