Skip to content

Instantly share code, notes, and snippets.

@holmberd
Created May 28, 2021 15:08
Show Gist options
  • Save holmberd/22ca75648d50aa5ccb4ac2508a206325 to your computer and use it in GitHub Desktop.
Save holmberd/22ca75648d50aa5ccb4ac2508a206325 to your computer and use it in GitHub Desktop.
React Hook: useVisibleElementsIndex
import { useState, useEffect } from 'react';
import { debounce } from 'lodash';
/**
* React Hook that returns an index for the right-most element that is horizontally
* visible within the boundaries of the container.
*/
function useVisibleElementsIndex(containerRef, items) {
const [visibleElementsIndex, setVisibleElementsIndex] = useState(0);
const didUpdate = () => {
if (!containerRef || !containerRef.current) {
return;
}
const containerElement = containerRef.current;
const elements = Array.from(containerElement.children)
if (!elements.length) {
return setVisibleElementsIndex(0);
}
const visibleIndex = elements
.reverse()
.findIndex(element => element.getBoundingClientRect().right < containerElement.getBoundingClientRect().right);
return setVisibleElementsIndex(elements.length - visibleIndex);
}
useEffect(() => {
if (!containerRef || !containerRef.current) {
return;
}
didUpdate();
const debouncedDidUpdate = debounce(didUpdate, 150);
let resizeObserver = new ResizeObserver(debouncedDidUpdate);
resizeObserver.observe(containerRef.current);
return () => {
if (resizeObserver) {
debouncedDidUpdate.cancel();
resizeObserver.disconnect();
resizeObserver = null;
}
}
}, [containerRef.current, items])
return visibleElementsIndex;
}
export default useVisibleElementsIndex;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment