typescriptintermediate
useScrollPosition Hook
Tracks window scroll position with throttling for performance-sensitive scroll effects.
typescriptPress ⌘/Ctrl + Shift + C to copy
import { useState, useEffect, useRef } from 'react';
interface ScrollPosition {
x: number;
y: number;
}
export function useScrollPosition(throttleMs = 100): ScrollPosition {
const [position, setPosition] = useState<ScrollPosition>({ x: 0, y: 0 });
const lastUpdate = useRef(0);
useEffect(() => {
const handleScroll = () => {
const now = Date.now();
if (now - lastUpdate.current < throttleMs) return;
lastUpdate.current = now;
setPosition({ x: window.scrollX, y: window.scrollY });
};
window.addEventListener('scroll', handleScroll, { passive: true });
return () => window.removeEventListener('scroll', handleScroll);
}, [throttleMs]);
return position;
}Use Cases
- Sticky headers
- Scroll-based animations
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
typescriptbeginner
useDebounce — Debounced Value Hook
Debounce any rapidly-changing value with a configurable delay. Useful for search inputs and resize handlers.
Best for: Search-as-you-type
#hooks#debounce
typescriptintermediate
Infinite Scroll with Intersection Observer
Load more items as the user scrolls using IntersectionObserver. No external libraries required.
Best for: Feed pagination
#infinite-scroll#intersection-observer
typescriptintermediate
useIntersectionObserver Hook
Track element visibility with the Intersection Observer API for lazy loading and scroll animations.
Best for: Lazy loading images
#hooks#intersection-observer
typescriptadvanced
Virtualized List Component
Render large lists efficiently by only rendering visible items with calculated scroll positioning.
Best for: Rendering 10k+ item lists
#virtualization#performance