I want to fetchMore
data when onscroll
reaches the bottom. The issue I have is that I get duplicate elements thus console yelling at me as well that I nee unique element keys
. I'm getting the correct data in the graphql playground so it's an issue in my react
component. Does this logic make sense? What's going wrong here?
class App extends Component {
isBottom = (fetchMore, data) => {
window.onscroll = () => {
if (
data &&
data.infiniteScrollMovies &&
data.infiniteScrollMovies.hasMore &&
window.innerHeight + document.documentElement.scrollTop === document.documentElement.offsetHeight
) {
console.log('YES!')
this.fetchMoreData(fetchMore, data)
}
}
}
fetchMoreData = (fetchMore, data) => {
fetchMore({
variables: {
offset: data.infiniteScrollMovies.newOffset,
},
updateQuery: (prev, { fetchMoreResult }) => {
if (!fetchMoreResult) return prev
return {
...fetchMoreResult,
infiniteScrollMovies: {
...fetchMoreResult.infiniteScrollMovies,
movies: [...prev.infiniteScrollMovies.movies, ...fetchMoreResult.infiniteScrollMovies.movies],
},
}
},
})
}
render() {
return (
<div className="flex flex-column">
<Query query={ALL_MOVIES} notifyOnNetworkStatusChange={true} fetchPolicy="network-only">
{({ data, loading, error, fetchMore }) => {
if (error) return <h1>{error.message}</h1>
this.isBottom(fetchMore, data)
return (
<div>
{data &&
data.infiniteScrollMovies &&
data.infiniteScrollMovies.movies.map(m => (
<article key={m.id}>
// ... rendering an element
</article>
))}
<div>{loading && <h1 className="red text-center">Loading...</h1>}</div>
Here's my query:
export const ALL_MOVIES = gql`
query infiniteScrollMovies($offset: Int) {
infiniteScrollMovies(offset: $offset, limit: 16) {
movies {
image_url
title
id
}
hasMore
newOffset
}
}
`
Use the variables
parameter in updataeQuery
to handle this scenario, basically you need to prevent the appending in cache if already its done.
Change your updateQuery to below
updateQuery: (prev, { variables, fetchMoreResult }) => {
// Return the prev values, if it allready has the length specified by offset
// thereby preventing duplicate values in cache.
if (!fetchMoreResult ||
prev.infiniteScrollMovies.movies.length > variables.offset)
return prev