I've seen tutorials that demonstrates how to do this but all that I've seen uses "window" or examples where the element comes in view from the bottom of a page. I have a modal with a fixed height that scrolls:
const ItemMarkup = forwardRef(({user}, ref) => <li ref={ref}>...</li>)
// This opens up in a modal: https://headlessui.dev/react/dialog
<div className="content">
{/** Tailwind's fixed height 'h-96' */}
<ul ref={scrollRef} className="h-96 overflow-scroll">
{users.map((user, index) =>
<ItemMarkup
{/** I'm looking for the last item/element to come in this view (ul) */}
ref={users.length === index + 1 ? ref : null}
key={user.id}
user={user}
/>
)}
</ul>
</div>
I've looked at this demo but again, it's for the entire page/window. Then I've tried using this function:
// element would be the ref.current
// target would be scrollRef
// But this always return false
function isInViewport(element, target) {
const rect = element.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= target.innerHeight &&
rect.right <= target.innerWidth
);
}
Here's how I tried the attempt:
const ref = useRef()
const scrollRef = useRef()
// From the demo link above
const onScreen = useOnScreen(ref)
// No idea if I need this
const [scrolling, setScrolling] = useState(false)
useEffect(() => {
const onScroll = e => {
setScrolling(true)
console.log(isInViewport(ref.current, scrollRef))
};
scrollRef?.current.addEventListener("scroll", onScroll);
//console.log(ref, onScreen)
return () => scrollRef?.current.removeEventListener("scroll", onScroll);
}, [ref, onScreen, scrolling])
This seems all wrong. Is there a react hook I could to determine when a specific element comes in a modal view or any scrollable view that I specify and not the document view? I just cannot find any documentation/tutorials on this.
I'm creating an infinite scroll. When the last items comes in view, of the modal, I then trigger a function to fetch more data.
I guess I have over complicated things:
useEffect(() => {
const onScroll = e => {
console.log(isInViewport(e.target))
};
scrollRef?.current.addEventListener("scroll", onScroll);
return () => scrollRef?.current.removeEventListener("scroll", onScroll);
}, [])
function isInViewport(element) {
return element.scrollHeight - element.scrollTop === element.clientHeight
}
Now when I scroll to the bottom, I see a console log of true.