Files
2026-08-20 14:17:40 +02:00

35 lines
1.0 KiB
TypeScript

import { useEffect, useRef } from "react";
type UseElementVisibilityOptions = {
onVisibilityChange?: (isVisible: boolean) => void;
};
export function useElementVisibility({ onVisibilityChange }: UseElementVisibilityOptions = {}) {
const ref = useRef<HTMLDivElement>(null);
const isVisibleRef = useRef(false);
const callbackRef = useRef(onVisibilityChange);
// oxlint-disable-next-line react/refs -- This ref intentionally coordinates an imperative integration outside React state.
callbackRef.current = onVisibilityChange;
useEffect(() => {
const el = ref.current;
if (!el) return;
const observer = new IntersectionObserver(
([entry]) => {
const nowVisible = entry.isIntersecting;
if (isVisibleRef.current !== nowVisible) {
isVisibleRef.current = nowVisible;
callbackRef.current?.(nowVisible);
}
},
{ threshold: 0 }
);
observer.observe(el);
return () => observer.disconnect();
}, []);
return { ref, isVisibleRef };
}