Reputation: 79
I am using Infinite scroll component. It is working but it is requesting same endpoint multiple times ( 3 -4 times) . With my React knowledge, let me explain what is happening:
Because I am setting initialLoad={true}, so the loadMore function will be invoked right after component rendered. I can set initialLoad={false} but it doesn't fetch data in the initial render
Index.js
export default function index() {
const { tracks, error, loading, loadMore, hasMore } = usePublicTracks(
myApiEndPoint.TRENDING_TRACKS,
5,
);
return (
<div>
<Main>
<InfiniteScroll
initialLoad={true} //call loadMore function right after component rendered
pageStart={0}
loadMore={loadMore}
hasMore={hasMore}
>
<TrackList>
{tracks.map((track, i) => (
<TrackItem key={i}
track={track}
/>
))}
</TrackList>
{loading && hasMore && (
<div className="">
<Spin />
</div>
)}
</InfiniteScroll>
</Main>
</div>
);
}
usePublicTracks.js
export const usePublicTracks = (endpoint, limit) => {
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [offset, setOffset] = useState('');
const [tracks, setTracks] = useState([])
const [hasMore, setHasMore] = useState(true);
console.log('tracks', tracks)
const loadMore = async params => {
try {
console.log('hello22222222222222222222222222222222222222222')
const res = await myApiAxiosInstance.get(endpoint, {
params: {
limit: limit,
lastVisible: offset
}
});
setLoading(false);
setTracks([...tracks, ...(res.data.collection)])
setOffset(res.data.lastVisible)
if (res.data.lastVisible == "end") setHasMore(false);
} catch (error) {
setLoading(false);
setError(error.message);
}
};
return {
error,
loading,
tracks,
loadMore,
hasMore
};
};
When I wrap loadMore func in useEffect, it show error Hooks can only be called inside of the body of a function component.:
const loadMore = async params => {
useEffect(() => {
const loadMoreOnce = async () => {
//some logic
};
loadMoreOnce();
}, []);
};
My question is how to call the load more function once. Then call it every scrolling to the bottom of window ? How to prevent to request same endpoint multiple times ?
Upvotes: 1
Views: 1227
Reputation: 538
const isLoading = false;
const myComponent = () => {
useEffect(() => {
loadMore(); // initial call, this useEffect equivalent to componentDidMount
}, []);
if (!isLoading && document.body.scrollTop >= document.body.offsetTop) {
console.log('loading, should see this once');
isLoading = true;
loadMore(); // here, after loadMore finished you need to resolve isLoading to false
}
return (<div>My component</div>);
}
Try to find all calls of loadMore function calls, maybe it is called in some other places as well, change offset from beginning of page, check hasMore condition to be chaged correctly, because several calls can also come from InfiniteScroll itself, when it thinks you hit bottom several times.
Upvotes: 1