So I'm working on a website that has infinite scrolling and sorting/filtering. The issue is that when the sortBy
method is being changed, I need to reset the offset for the pagination for the infinite scrolling page.
Here's the code for the component:
function Listings({ setListingCount, sortBy }) {
const [listings, setListings] = useState([]);
const [isInitialLoading, setIsInitialLoading] = useState(true);
const [isLoading, setIsLoading] = useState(true);
const [apiError, setApiError] = useState(false);
const [offset, setOffset] = useState(0);
const [hasMore, setHasMore] = useState(true);
const limit = 12;
const observer = useRef();
const lastListingElementRef = useCallback((node) => {
if (isLoading) {
return;
}
if (observer.current) {
observer.current.disconnect();
}
observer.current = new IntersectionObserver((entries) =>
{
if (entries[0].isIntersecting && hasMore) {
setOffset((prevOffset) => prevOffset + limit);
}
});
if (node) {
observer.current.observe(node);
}
}, [isLoading, hasMore]);
function resetListings() {
setListings([]);
setIsInitialLoading(true);
setApiError(false);
setOffset(0);
setHasMore(true);
setListingCount('0');
}
useEffect(() => {
resetListings();
}, [sortBy]);
useEffect(async () => {
try {
setIsLoading(true);
const response = await axios.get(
'listings',
{
params: {
offset,
limit,
sb: sortBy
}
}
);
setListings((prevListingIds) => [
...new Set(
[...prevListingIds, ...response.data.rows]
)
]);
setListingCount(response.data.count);
setHasMore(response.data.rows.length > 0);
setIsLoading(false);
setIsInitialLoading(false);
} catch (error) {
setApiError(true);
setIsLoading(false);
setIsInitialLoading(false);
}
}, [sortBy, offset]);
return();
}
The first useEffect
is being used to reset the states if the sortBy
changes. The second useEffect
is being used to load more data whenever the offset changes or if the sortBy
changes. What's happening currently is when the user changes the sortBy
when offset is not 0 (let's say 12), then the second useEffect
is making a get request with offset = 12
before the first useEffect
is able to reset the offset back to 0. But once the offset is reset to 0 by the first useEffect
, another get request is made with offset = 0
, so now it renders 24 listings instead of 12, and it's in the wrong order.
How should I be dealing with useEffect
s that aren't guaranteed to run in the order that I expect it to? Is there another way to implement this logic? Thank you for any help that can be provided!