Skip to content

Instantly share code, notes, and snippets.

@sibelius
Forked from BorisTB/App.js
Created August 20, 2019 20:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sibelius/a6c5afb73d7954f9d8e0c81bcb417932 to your computer and use it in GitHub Desktop.
Save sibelius/a6c5afb73d7954f9d8e0c81bcb417932 to your computer and use it in GitHub Desktop.
Demo of helper hooks for automatic refetch on sort/pagination change
const App = React.memo(
({
node: {
items: { totalCount, ...items }
},
relay
}) => {
const [fulltext, setFulltext] = useState('')
const fulltextDebounced = useDebounce(fulltext, 300)
const [{ sort, order }, updateSort] = useSort({ sort: 'name', order: 'asc' })
const [{ first, offset }, paginationProps] = usePagination({ first: 25, offset: 0 }, totalCount)
const [fetching] = useAutoRefetch(
relay,
{
sort,
order,
first,
offset,
fulltext: fulltextDebounced
}
)
return (
// ...jsx
)
}
)
const useAutoRefetch = (relay, refetchVars, { onSuccess } = {}) => {
const [fetching, setFetching] = useState(false)
useEffect(
() => {
setFetching(true)
const request = relay.refetch(
prevVars => ({
...prevVars,
...refetchVars
}),
undefined,
error => {
if (!error && typeof onSuccess === 'function') {
onSuccess(refetchVars)
}
setFetching(false)
}
)
return () => {
// cancel ongoing refetch when new starts
request.dispose()
}
},
[...Object.values(refetchVars)] // "watch" refetch vars for change
)
return [fetching]
}
const usePagination = ({ first: initFirst, offset: initOffset }, totalCount) => {
const [{ page, numberOfRows }, updateRows] = useState(() => ({
page: initOffset === 0 || totalCount === 0 || totalCount < initOffset ? 1 : initOffset / initFirst + 1,
numberOfRows: initFirst
}))
const offset = useMemo(() => (page - 1) * numberOfRows, [page, numberOfRows])
useEffect(
() => {
// go to first page if the current page is empty
if (page > 1 && totalCount <= offset) {
updateRows(prevState => ({
...prevState,
page: 1
}))
}
},
[totalCount, page, offset]
)
// props for my pagination component
const paginationProps = {
total: totalCount,
page,
numberOfRows,
updateRows
}
return [{ first: numberOfRows, offset }, paginationProps]
}
const useSort = initValues => {
const [{ sort, order }, updateSortState] = useState(initValues)
const changeSort = newSort => {
const newOrder = newSort === sort ? (order === 'asc' ? 'desc' : 'asc') : 'asc'
updateSortState({ sort: newSort, order: newOrder })
}
return [{ sort, order }, changeSort]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment