Usage
Tracks whether an element is visible in the viewport, useful for lazy loading, animations, and infinite scroll.
import { useIntersectionObserver } from '@kivora/react';
function LazyImage({ src }: { src: string }) {
const { ref, isIntersecting } = useIntersectionObserver({ once: true });
return (
<div ref={ref}>
{isIntersecting ? (
<img src={src} alt="Lazy loaded" />
) : (
<div className="placeholder">Loading...</div>
)}
</div>
);
}
Parameters
options
UseIntersectionObserverOptions
Configuration object for the intersection observer
Root margin using CSS margin syntax (e.g., '0px 0px -100px 0px')
threshold
number | number[]
default:"0"
Intersection threshold(s) from 0 to 1. Use array for multiple thresholds (e.g., [0, 0.5, 1])
Whether to stop observing after the first intersection
Returns
ref
RefObject<HTMLElement | null>
Attach this ref to the element you want to observe
true when the element is intersecting the viewport
entry
IntersectionObserverEntry | null
The raw IntersectionObserverEntry, or null before first observation
Examples
import { useIntersectionObserver } from '@kivora/react';
function FadeIn({ children }: { children: React.ReactNode }) {
const { ref, isIntersecting } = useIntersectionObserver({
once: true,
threshold: 0.5,
});
return (
<div
ref={ref}
style={{
opacity: isIntersecting ? 1 : 0,
transform: isIntersecting ? 'translateY(0)' : 'translateY(20px)',
transition: 'opacity 0.5s, transform 0.5s',
}}
>
{children}
</div>
);
}
import { useIntersectionObserver } from '@kivora/react';
import { useEffect } from 'react';
function InfiniteList({ items, loadMore }: { items: any[]; loadMore: () => void }) {
const { ref, isIntersecting } = useIntersectionObserver({
rootMargin: '100px',
});
useEffect(() => {
if (isIntersecting) {
loadMore();
}
}, [isIntersecting, loadMore]);
return (
<div>
{items.map((item, i) => (
<div key={i}>{item}</div>
))}
<div ref={ref}>Loading more...</div>
</div>
);
}
Track visibility percentage
import { useIntersectionObserver } from '@kivora/react';
function VisibilityTracker() {
const { ref, entry } = useIntersectionObserver({
threshold: [0, 0.25, 0.5, 0.75, 1],
});
const visibilityPercentage = entry
? Math.round(entry.intersectionRatio * 100)
: 0;
return (
<div ref={ref} style={{ height: '200px', background: '#f0f0f0' }}>
Visible: {visibilityPercentage}%
</div>
);
}
Lazy load with placeholder
import { useIntersectionObserver } from '@kivora/react';
function LazyComponent() {
const { ref, isIntersecting } = useIntersectionObserver({
once: true,
rootMargin: '200px',
});
return (
<div ref={ref} style={{ minHeight: '400px' }}>
{isIntersecting ? (
<ExpensiveComponent />
) : (
<div className="skeleton-loader" />
)}
</div>
);
}