fix: re-observe sentinel on data load so IO re-fires when still in trigger zone#430
Conversation
…igger zone IntersectionObserver only fires on intersection state changes. When the sentinel stayed continuously inside the trigger zone across a data load (e.g. user holding the End key), no new event fired and the component got stuck until the user scrolled away and back. Force a fresh callback by calling unobserve + observe on the existing observer in Effect 2a. Fixes [ankeetmaini#429](ankeetmaini#429)
Covers issue [ankeetmaini#429](ankeetmaini#429): verifies that on dataLength change the existing IntersectionObserver has unobserve(sentinel) + observe(sentinel) called on it (forcing a fresh callback in real browsers) and that the same observer instance is reused rather than torn down. Both tests fail against the pre-fix source.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #430 +/- ##
==========================================
+ Coverage 95.87% 96.22% +0.35%
==========================================
Files 4 4
Lines 194 212 +18
Branches 65 67 +2
==========================================
+ Hits 186 204 +18
Misses 4 4
Partials 4 4 🚀 New features to boost your workflow:
|
|
Hey @justanotheranonymoususer, thanks for putting up the PR! Before we merge, could you share a minimal CodeSandbox or StackBlitz reproducing your original setup, specifically the |
|
I'm using a different computer right now, but it was a standard usage as in the example and I just was holding end. Using Windows. You can't reproduce it without the fix? |
|
This is my usage in the code: const [loadedItems, setLoadedItems] = useState(100);
//...
const { sentinelRef } = useInfiniteScroll({
dataLength: loadedItems,
next: () =>
setLoadedItems((prev) =>
Math.min(prev + 100, dataset.length)
),
hasMore: loadedItems < dataset.length,
scrollableTarget: 'ContentWrapper',
}); |
|
We reproduced it locally with Setup that reproduces it without any keyboard interaction: const dataset = Array.from({ length: 500 }, (_, i) => i);
const [loadedItems, setLoadedItems] = useState(5); // few enough that sentinel is visible on mount
const { sentinelRef } = useInfiniteScroll({
dataLength: loadedItems,
next: () => setLoadedItems((prev) => Math.min(prev + 5, dataset.length)),
hasMore: loadedItems < dataset.length,
scrollableTarget: 'ContentWrapper',
});With a 500px The When you get a chance, it would be great if you could share a CodeSandbox or a short recording of your original setup so we can make sure the fix covers your exact case before merging. |
|
It will take me some time to return to it. You verified that it fixes the issue, and it worked for me when I tried it, and I added tests, so I think it's good to merge. |
No description provided.