Last active
November 17, 2020 17:09
-
-
Save zebapy/5e899cf55ff0828056b718c657bbc29d to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| import { useState } from 'react'; | |
| import { useQuery } from '@apollo/client'; | |
| import update from 'immutability-helper'; | |
| import get from 'lodash/get'; | |
| export const usePagerQuery = ( | |
| query, | |
| { variables, updateQuery, itemsPath, countPath, skip } | |
| ) => { | |
| const [loadingMore, setLoadingMore] = useState(false); | |
| const { data, loading, fetchMore } = useQuery(query, { | |
| variables, | |
| skip | |
| }); | |
| const items = get(data, itemsPath, []); | |
| const total = get(data, countPath, 0); | |
| const count = items.length; | |
| const hasNextPage = count !== total; | |
| const loadMore = async () => { | |
| setLoadingMore(true); | |
| const result = await fetchMore({ | |
| query, | |
| variables: { | |
| ...variables, | |
| skip: count | |
| }, | |
| updateQuery: (previousResult, { fetchMoreResult }) => { | |
| if (!fetchMoreResult) { | |
| return previousResult; | |
| } | |
| return update(previousResult, updateQuery(fetchMoreResult)); | |
| } | |
| }); | |
| setLoadingMore(false); | |
| return result; | |
| }; | |
| return { | |
| data, | |
| items, | |
| total, | |
| count, | |
| loading, | |
| loadMore, | |
| hasNextPage, | |
| loadingMore | |
| }; | |
| }; |
This file contains hidden or 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
| import React from 'react'; | |
| import PropTypes from 'prop-types'; | |
| import { Blankslate, Text, Button, Spinner } from 'components'; | |
| import { usePagerQuery } from 'hooks/use-pager-query'; | |
| const Pager = ({ | |
| query, | |
| variables, | |
| updateQuery, | |
| children, | |
| itemsPath, | |
| countPath, | |
| buttonProps, | |
| showToolbar, | |
| skip, | |
| showNoResultsBlankslate = true, | |
| blankslateProps = { | |
| title: 'No results found', | |
| text: 'Try adjusting filters or searching for something else' | |
| } | |
| }) => { | |
| const { | |
| data, | |
| items, | |
| total, | |
| count, | |
| loading, | |
| loadMore, | |
| loadingMore, | |
| hasNextPage | |
| } = usePagerQuery(query, { | |
| variables, | |
| skip, | |
| itemsPath, | |
| countPath, | |
| updateQuery | |
| }); | |
| if (loading) { | |
| return <Spinner size="lg" centered />; | |
| } | |
| if (showNoResultsBlankslate && items && count === 0) { | |
| return <Blankslate {...blankslateProps} />; | |
| } | |
| return ( | |
| <div> | |
| {children({ | |
| data, | |
| loading, | |
| totalCount: total | |
| })} | |
| {hasNextPage && ( | |
| <Text textAlign="center" py={4}> | |
| <Button | |
| kind="primary" | |
| size="lg" | |
| onClick={loadMore} | |
| loading={loadingMore} | |
| label={ | |
| loadingMore | |
| ? 'Loading more...' | |
| : `Load ${variables.first ? variables.first : ''} more` | |
| } | |
| data-cy="load-more-btn" | |
| {...buttonProps} | |
| /> | |
| </Text> | |
| )} | |
| </div> | |
| ); | |
| }; | |
| Pager.propTypes = { | |
| buttonProps: PropTypes.object, | |
| children: PropTypes.func.isRequired, | |
| // TODO: change these to use lodash.get and pass a path instead | |
| countPath: PropTypes.string.isRequired, | |
| itemsPath: PropTypes.string.isRequired, | |
| query: PropTypes.object.isRequired, | |
| updateQuery: PropTypes.func, | |
| variables: PropTypes.object | |
| }; | |
| export default Pager; |
This file contains hidden or 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
| import React from 'react'; | |
| import { gql } from '@apollo/client'; | |
| import Pager from 'components/Pager'; | |
| import Decks from '../components/Decks'; | |
| export const decksQuery = gql` | |
| query decksPage( | |
| $orderBy: DeckOrderBy | |
| $skip: Int | |
| $filter: DeckFilter | |
| $first: Int | |
| ) { | |
| decks(skip: $skip, filter: $filter, orderBy: $orderBy, first: $first) { | |
| ...Decks | |
| } | |
| decksMeta(filter: $filter) { | |
| count | |
| } | |
| } | |
| ${Decks.fragments.decks} | |
| `; | |
| const DecksContainer = ({ | |
| showTotals, | |
| filter, | |
| orderBy = 'created_at_DESC' | |
| }) => ( | |
| <Pager | |
| query={decksQuery} | |
| variables={{ | |
| first: 9, | |
| filter, | |
| orderBy | |
| }} | |
| countPath="decksMeta.count" | |
| itemsPath="decks" | |
| updateQuery={data => ({ | |
| decks: { | |
| $push: data.decks | |
| } | |
| })} | |
| children={({ data, totalCount }) => ( | |
| <Decks | |
| decks={data.decks} | |
| totalCount={totalCount} | |
| showTotals={showTotals} | |
| /> | |
| )} | |
| /> | |
| ); | |
| export default DecksContainer; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment