I'm attempting to make a infinite scroll pagination in my React-Relay frontend, but without a success.
At this moment, I have this React component ...
class List extends Component {
state = { loading: false };
componentDidMount() {
window.onscroll = () => {
if (!this.state.loading
&& (window.innerHeight + window.scrollY)
>= document.body.offsetHeight) {
this.setState({loading: true}, () => {
this.props.relay.setVariables({
count: this.props.relay.variables.count + 5
}, (readyState) => {
if (readyState.done) {
this.setState({ loading: false });
}
});
});
}
}
}
render() {
return (
<div>
{this.props.viewer.products.edges.map(function(product, i) {
return (<Item key={i} product={product.node} />);
})}
</div>
);
}
};
... wrapped in Relay container
export default Relay.createContainer(List, {
initialVariables: {
count: 5
},
fragments: {
viewer: () => Relay.QL`
fragment on Viewer {
products(first: $count) {
total
edges {
node {
${Item.getFragment('product')}
}
}
}
}
`,
}
});
The logic behind this seems quite easy. If you reach a certain scrollY position, set to count variable a new inceremented value, which extends your list of Edges.
But this concept will lead to a situation, where in the beginning I query the database for first 5 records, but lately while I keep scrolling a will query for N+5 records. In the end I will query the database for a whole table (thousands of records)! Which is quite unacceptable.
So I'm trying to implement a cursors, but I don't know how to just fetch data from a connection and extend the result. This approach returns me a "paginated" list.
Also, the above code gives me this error, when I scroll down
resolveImmediate.js?39d8:27 Uncaught Invariant Violation: performUpdateIfNecessary: Unexpected batch number (current 19, pending 18)
I will be very thankful for any help or example!
Problem solved!
About my concern of fetching N+5 records over and over again with each scroll, it seems that Relay is quite intelligent, because it automatically "paginate" my connection by querying cursor and managing the after arg in my connection.
And with little help from graphql-sequelize on my backend, it simply turns into this query
SELECT ... FROM product ORDER BY product.id ASC LIMIT 5 OFFSET 10
Which actually solves my first problem about the performance. :)
So my Relay.QL query has underhood transpiled into this
query ListPage_ViewerRelayQL($id_0:ID!) {
node(id:$id_0) {
...F1
}
}
fragment F0 on Product {
id,
title,
price
}
fragment F1 on Viewer {
_products4tSFq4:products(after:"YXJyYXljb25uZWN0aW9uJDUkNA==",first:5) {
edges {
cursor,
node {
id,
...F0
}
},
pageInfo {
hasNextPage,
hasPreviousPage
}
},
id
}
and when I ran this query on my GraphQL backend, it returned me empty result
{
"data": {
"node": null
}
}
Then I immediately realized where is the problem and why my Relay crashes down.
The problem is with refetching the viewer. I did not properly implemented nodeDefinitions and when the viewer ID hit idFetcher and typeResolver, it failed and returned a null. After that on the client side, Relay was unable to finish the refetching of my connection and crashed down!
After small repairment and fixes on the Backend-side, my infinite scroll works like a charm! :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With