How do I deal with two useEffect hooks where one useEffect dependency is affecting another useEffect dependency?

Viewed 452

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 useEffects 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!

0 Answers
Related