I have a function newsFeed
which is called by useEffect and makes a request to an endpoint to fetch all posts made by the logged in user as well as any users they follow, and then saves the data response to the state:
const [posts, setPosts] = useState([])
const [page, setPage] = useState(1)
useEffect(() => {
newsFeed();
}, []
const newsFeed = async () => {
await axios.post(
`${process.env.REACT_APP_API}/news-feed/${page}`,
)
.then((res) => {
setPosts(res.data);
setPage(page + 1);
})
.catch((err) => {
console.log(err);
});
};
router.post('/news-feed/:page', newsFeed);
exports.newsFeed = async (req, res) => {
try {
const user = await User.findById(req.body.user._id);
let following = user.following;
following.push(req.body.user._id);
const currentPage = req.params.page || 1;
const perPage = 5;
const posts = await Post.find({ postedBy: { $in: following } })
.skip((currentPage - 1) * perPage)
.sort({createdAt: -1})
.limit(perPage);
res.json(posts);
} catch (err) {
console.log(err);
}
};
I want to use react-infinite-scroll-component
to fetch only the first 20 posts on page load, then another 20 when user scrolls to the bottom etc.
I currently have this code to render the posts:
<div id='scrollableDiv' style={{ overflow: 'auto' }}>
<InfiniteScroll
dataLength={20}
next={newsFeed}
hasMore={true}
loader={<FontAwesomeIcon icon={faSpinner} spin />}
endMessage={
<p style={{ textAlign: 'center' }}>
<b>Yay! You have seen it all</b>
</p>
}
scrollableTarget='scrollableDiv'
>
{posts.map((post) => (
...)}
</InfiniteScroll>
</div>
What is now happening is that only the first 20 posts are rendered, with the loading spinner continuously displayed below.
I have tried adding page
as a dependency to the useEffect callback and this does result in loading the posts in blocks of 20, however they are rendered automatically each second and overlap the previous block as if the app is literally changing the page and when all have been rendered an empty screen is displayed.