I'm using this hook in order to get the offset from the top of the page to the top of an element. It seemed to work fine until I started navigating through my react-router page routes.
const usePosition = () => {
const [dimensions, setDimensions] = useState({
height: window.innerHeight,
width: window.innerWidth,
});
const [offsets, setOffsets] = useState({
offsetTop: 0,
offsetBottom: 0,
});
const ref = useRef();
const handleResize = () => {
setDimensions({
height: window.innerHeight,
width: window.innerWidth,
});
};
useLayoutEffect(() => {
const position = ref.current.getBoundingClientRect();
setOffsets({
offsetTop: window.pageYOffset + position.top,
offsetBottom: window.pageYOffset + position.bottom,
});
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, [ref, dimensions, setOffsets]);
return [ref, offsets, dimensions];
};
export default usePosition;
Upon loading the website this ImagesBanner element would work fine but when I would leave and then go back to the route with my ImagesBanner, getBoundingClientRect(); returns an incorrect top and bottom value, therefore, throwing off the animation.
const ImagesBanner = () => {
const [images, setImages] = useState([]);
const [ref, offsets, dimensions] = usePosition();
const { scrollY } = useViewportScroll();
const fetchImages = async () => {
const images = await getClientImages();
setImages(images);
};
const transformX = useTransform(
scrollY,
[offsets.offsetTop - dimensions.height, offsets.offsetBottom],
[
(images.length * 450 - 200) * -1 + dimensions.width / 2,
images.length * 450 - 200 - dimensions.width / 2,
]
);
useEffect(() => {
fetchImages();
}, []);
return (
<div className="images-banner">
<div className="images-banner__title">
<h2 className="heading">Our Clients</h2>
</div>
<motion.div
className="images-banner__slider"
ref={ref}
style={{ left: transformX }}
>
{images.map((image) => (
<div key={image.node.id} className="images-banner__slide">
<img
src={image.node.logo.url}
alt={image.node.client}
/>
</div>
))}
</motion.div>
</div>
);
};
export default ImagesBanner;
Any help would be greatly appreciated.