Hello everyone,
In this article we will see how to call an event from React compoenent when we reach end of the page. This functionality is useful when we have to make API calls based on pageIndex and pageSize. For example, if there are millions of data return by your API and you don’t want to show all the result in one single API call instead if you make call by pageIndex, pageSize (if your API permits) then when end of the page is scrolled, we can make API call to the server which return few more data and so on. Well, there many custom components available in github and this approach is more like FlatList in React Native.
Let’s say I have component called SearchResult and this will make API call and returns the result. The result will be loaded into other component which will loop through all the items, once the user reach end of the page then it will automatically make an API call with increased pageIndex and pageSize, because my API accepts pagination and payload. Main thing we need to notice here is how we handle event trigger when user reaches end of the page.
Well I am using typescript and office ui fabric for design, so my component looks more like below
interface ISearchResultProps {
searchInfo: any;
}
interface ISearchResultState {
resultAll: any;
isFetched: boolean;
isError: boolean;
isLoadingMore: boolean;
loadMoreError: any;
isEnd: boolean;
error: any;
}
export default class SearchResult extends React.Component<
ISearchResultProps,
ISearchResultState
> {
constructor(props: ISearchResultProps) {
super(props);
this.state = {
resultAll: {},
isFetched: false,
isError: false,
isLoadingMore: false,
isEnd: false,
loadMoreError: "",
error: ""
};
this.handleScroll = this.handleScroll.bind(this);
}
public async componentDidMount() {
// EventListener for scroll
window.addEventListener("scroll", this.handleScroll);
// First API call
let resultAll: any = await getResultsFromAPI(this.props.searchInfo);
if (resultAll) {
this.setState({
resultAll: resultAll,
isFetched: true
});
} else {
this.setState({
isFetched: true,
isError: true
});
}
}
// this function will be called when user scrolling
private handleScroll() {
// condition to check, End of the page reached?
if (window.innerHeight + window.scrollY >= document.body.offsetHeight) {
const resultAll = this.state.resultAll;
let searchQ = this.props.searchInfo;
// Condition to avoid multiple API call when user reach end of Page before previous call is over
if (resultAll.Common && !this.state.isLoadingMore && !this.state.isEnd) {
this.setState(
{
isLoadingMore: true
},
async () => {
try {
searchQ.pageIndex = searchQ.pageSize;
searchQ.pageSize = searchQ.pageSize + 20;
searchQ.PollURL = resultAll.Common.PollURL;
const newResult: any = await getResultsFromAPI(searchQ);
if (newResult && newResult.Results.length > 0) {
// pushing values to existing state by using immutable-helper
// https://www.npmjs.com/package/immutability-helper
const immutableResult = update(this.state.resultAll, {
Results: { $push: newResult.Results }
});
this.setState({
resultAll: immutableResult,
isLoadingMore: false
});
} else {
this.setState({
isEnd: true
});
}
} catch {
this.setState({
loadMoreError: "Error while getting more data from the server.",
isLoadingMore: false
});
}
}
);
}
}
}
public render(): JSX.Element {
return (
<div>
{!this.state.isFetched ? (
<Spinner
className="spinner-style"
size={SpinnerSize.large}
label="Getting, result..."
/>
) : this.state.isError ? (
<MessageBar
title={`Error while getting data from server. - ${
this.state.error
}`}
/>
) : this.state.resultAll.Results ? (
this.state.resultAll.Results.map((result: any, key: number) => {
return (
<div key={key}>
<Results resultInfo={result} />
</div>
);
})
) : (
<MessageBar title="Something went wrong" />
)}
{this.state.resultAll && this.state.resultAll.length <= 0 && (
<MessageBar title="No result found." />
)}
{this.state.loadMoreError && (
<MessageBar title="Something went wrong" />
)}
{this.state.isLoadingMore && !this.state.isEnd && (
<Spinner size={SpinnerSize.large} label="Loading, more results..." />
)}
{this.state.isEnd && <MessageBar title="End of search result" />}
</div>
);
}
}
Happy Coding
Ahamed
Leave a comment