Skip to content

v7.0 stops working if holding "End" key #429

Open

Description

I updated to v7 with useInfiniteScroll exactly like in the basic example. Unlike in previous version, now if I hold End, at some point it stops loading. If I scroll up and then down again it loads again.

Probably in addition to IntersectionObserver, you also need to make sure if it's not already visible at the time it's added to the DOM.

Activity

  1. justanotheranonymoususer commented on May 2, 2026

    @justanotheranonymoususer
    Author

    Adding this as a workaround worked for me:

      // IntersectionObserver fires only when the sentinel transitions across
      // threshold 0; holding End keeps it continuously inside the trigger zone so
      // the hook stops firing. A scroll listener catches each browser-applied
      // scroll (one per End keypress) and chains the next batch.
      const totalCount = myData.length;
      useEffect(() => {
        const root = document.getElementById('MyContentWrapper'); // scrollableTarget
        if (!root) {
          return;
        }
        const handleScroll = () => {
          if (root.scrollHeight - (root.scrollTop + root.clientHeight) > root.clientHeight) {
            return;
          }
          setInfiniteScrollLoadedItems((prev) =>
            prev < totalCount ? Math.min(prev + 30, totalCount) : prev
          );
        };
        root.addEventListener('scroll', handleScroll, { passive: true });
        return () => root.removeEventListener('scroll', handleScroll);
      }, [totalCount]);
  2. iamdarshshah commented on May 2, 2026

    @iamdarshshah
    Collaborator

    Thanks for the detailed report and the correct intuition on the root cause!

    This is a confirmed bug. The IntersectionObserver only fires on intersection changes, not the current state. When new data loads while the sentinel is already visible, Effect 2a resets the load guard but the IO never re-fires, leaving the component stuck until the user scrolls away and back. Your workaround (scroll up, then down) triggers a fresh intersection event, which is why it works.

    The fix is straightforward: after resetting the guard on new data, force the IO to re-evaluate by calling observer.unobserve(sentinel) + observer.observe(sentinel) on the existing observer instance. No API changes needed, this would be a patch release.

    If you're interested in contributing a fix, we'd love that and are happy to review a PR. The relevant code is in src/index.tsx, specifically Effect 2a (dataLength dep) and Effect 2b (the IO lifecycle). Happy to give more detail on the approach if it helps.

  3. justanotheranonymoususer commented on May 2, 2026

    @justanotheranonymoususer
    Author
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions