// @flow import React from 'react'; import type { Node } from 'react'; type InjectedItem = { node: Node, index?: number, replace?: boolean }; export default function useLastVisibleItem(injectedItem: ?InjectedItem, listRef: any) { const [injectedIndex, setInjectedIndex] = React.useState(injectedItem?.index); React.useEffect(() => { // Move to default injection index (last visible item) if (injectedItem && injectedItem.index === undefined) { // AD_INJECTION_DELAY_MS = average total-blocking-time incurred for // loading ads. Delay to let higher priority tasks run first. Ideally, // should use 'requestIdleCallback/requestAnimationFrame'. const AD_INJECTION_DELAY_MS = 1500; const timer = setTimeout(() => { if (listRef.current) { const screenBottom = window.innerHeight; const items = listRef.current.children; if (items.length) { let i = 2; // Start from 2, so that the min possible is index-1 for (; i < items.length; ++i) { const rect = items[i].getBoundingClientRect(); if (rect.top > screenBottom || rect.bottom > screenBottom) { break; } } setInjectedIndex(i - 1); return; } } // Fallback to index-1 (2nd item) for failures. No retries. setInjectedIndex(1); }, AD_INJECTION_DELAY_MS); return () => clearTimeout(timer); } }, []); return injectedIndex; }