I'm building a company's internal social network (it's actually a training project, not a real life application) and I'm struggling with a scroll event that's causing me troubles.
I'm using React 18 and React router dom v6.
I have a Home page displaying posts from all users 5 by 5 with an infinite scroll. I also have a Profile page which does the same with the posts from a specific user. My infinite scroll is built more or less like the one in this tutorial (the version without external library).
Everything works well on each page except in a particular scenario. Let's say I'm on the Home page, I scroll to the bottom and get 5 more posts, then click in the header on the link to my Profile page. The Profile page will display the 5 first posts twice, which is obviously not what I want.
But that only occurs if I was below the first 5 posts on the Home page before navigating to the Profile page. If I scroll back up before navigating, or if I don't fetch additional posts before navigating, no issue.
I believe I isolated the problem: it comes from the function that detects the bottom of the page and requests 5 more posts. In the scenario described above, this function gets triggered when arriving on the new page, on top of the initial render. So my initial render requests the first 5 posts from my API and my bottom-of-page function does the same.
Here is the function
window.onscroll = async function () {
if (loading === true) return;
if (
window.location.href.includes('profile') &&
window.innerHeight + Math.ceil(window.scrollY) >=
document.body.offsetHeight + 80 &&
reachedLastProfilePost === false
) {
FetchFivePostsFromUser();
}
};
So my issues are:
I tried convoluted fixes like implementing a scroll to top on navigation because my issue seems to disappear if I'm towards the top of the page before navigating. Also tried a timeout on the fetch requests, and other stuff. But I'm now officially out of ideas.
Well, that was my first question here on Stack Overflow and I'm not a native English speaker so please excuse me if it was too long or not clear enough. And don't hesitate to request clarifications or more code excerpts if needed.
It appears that my issue was that I was not cleaning up my bottom-of-page detection function properly.
Being new to React I was assuming that it was cleaning up the functional component and all its sub-functions when unmounting the component, i.e when I was leaving the page. But that was an incorrect asumption.
So what I did is I modified the function as below:
const handleScroll = async () => {
if (loading === true) return;
if (
window.location.href.includes('home') &&
window.innerHeight + Math.ceil(window.scrollY) >=
document.body.offsetHeight + 80 &&
reachedLastPost === false
) {
await FetchFivePosts();
}
};
And I passed it as a callback to an event listener that I create in a useEffect hook and properly clean with removeEventListener in the return of the useEffect.
Not 100% sure but I think that's the proper way to do it. I would appreciate if somebody can confirm it, though.