Created
October 20, 2019 13:53
-
-
Save necccc/4ea946178bd295822d8058fad7071944 to your computer and use it in GitHub Desktop.
Gists for Next.js & Apollo GraphQL Performance Tuning: Lists & pagination
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
// our GraphQL Query, | |
// get the name and ID of some Starships | |
export const getStarships = gql` | |
query getStarships { | |
starshipList { | |
items { | |
name | |
id | |
} | |
} | |
} | |
` | |
// a small component to list the data above | |
const List = (props) => (<div> | |
<ul> | |
{ | |
// data structure here matches the data structure in the query | |
props.data.starshipList.items.map(item => (<li key={item.id}> | |
{item.name} | |
</li>)) | |
} | |
</ul> | |
</div>) | |
// compose the component and the GraphQL Query together | |
// using the `graphql` method from react-apollo. | |
export default graphql(getStarships)(List) |
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
// our GraphQL Query, unchanged | |
export const getStarships = gql` | |
query getStarships { | |
starshipList { | |
items { | |
name | |
id | |
} | |
} | |
} | |
` | |
// the listing component | |
const List = (props) => (<div> | |
<ul> | |
{ | |
// NOTE, we're not including the property "starshipList" here | |
// just the data, with ids and names | |
props.data.map( item => (<li key={item.id}> | |
{item.name} | |
</li>)) | |
} | |
</ul> | |
</div>) | |
// we can use the tools in the Apollo Client to shape our component props | |
export default graphql(getStarships, { | |
props: ({data, ownProps}) => { | |
// data is the query result object | |
// ownProps is the props passed to the Component | |
const { | |
starshipPages, | |
loading | |
} = data | |
// compute new props, with only the data array, and the loading state | |
const newProps = { | |
loading, | |
data: starshipPages.items | |
} | |
// do not forget to include the originally received props (ownProps)! | |
return Object.assign({}, ownProps, newProps) | |
} | |
})(List) |
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
// our updated Query, now expecting a $page variable | |
// type is Int | |
// default value is 1 | |
export const getStarships = gql` | |
query getStarships($page: Int = 1) { | |
starshipList(page: $page) { | |
page | |
items { | |
name | |
id | |
} | |
} | |
} | |
` | |
// note that the data sctructure now contains the actual page number too | |
const List = (props) => (<div> | |
{ | |
// do something meaningful during loading, this is just some text | |
props.loading ? 'LOADING' : '' | |
} | |
<ul> | |
{ | |
props.data.map( item => (<li key={item.id}> | |
{item.name} | |
</li>)) | |
} | |
</ul> | |
<button onClick={e => props.loadPage(props.page + 1) }> | |
Load Page {props.page + 1} | |
</button> | |
</div>) | |
export default graphql(getStarships, { | |
options: { | |
// this is needed to auto-update the 'loading' prop | |
notifyOnNetworkStatusChange: true, | |
// fill parameters for the query here | |
variables: { | |
// first query will use 1 | |
page: 1 | |
}, | |
}, | |
props: ({data, ownProps}) => { | |
const { | |
// grab the fetchMore method | |
fetchMore, | |
// actual data | |
starshipPages: { items, page }, | |
// loading state indicator | |
loading | |
} = data | |
const newProps = { | |
// pass on loading state & data | |
loading, | |
page, | |
data: items, | |
// add a new function to the props, | |
// this will fetch the required page | |
loadPage: (nextPage) => { | |
// use fetchMore | |
return fetchMore({ | |
variables: { | |
page: nextPage | |
}, | |
updateQuery: (prev, { variables, fetchMoreResult }) => { | |
if (!fetchMoreResult) return prev; | |
// here you can concatenate the list | |
// with the already loaded and displayed ones (see `prev`) | |
// or just show the next page, like we do here | |
return Object.assign({}, fetchMoreResult, { variables }) | |
} | |
}) | |
} | |
} | |
// return the props | |
return Object.assign({}, ownProps, newProps) | |
} | |
})(List) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment