A focused collection of React hooks for performance monitoring, profiling, and Core Web Vitals measurement.
Live docs: react-perf-hooks docs website
Most hook libraries give you useDebounce and useLocalStorage. This one does one thing: helps you measure, diagnose, and understand performance in React apps.
All hooks are tree-shakeable, TypeScript-first, and have zero runtime dependencies (web-vitals is an optional peer dep).
npm install react-perf-hooksFor useWebVitals, also install the optional peer dependency:
npm install web-vitalsRequirements: React >= 16.8
| Hook | What it solves | Docs |
|---|---|---|
useRenderTracker |
Find components that re-render too often and why | Full docs |
useRenderBudget |
Warn when a single render commit exceeds a time budget (default: 16ms) | Full docs |
usePerformanceMark |
Precise timing of any code path via the Performance API | Full docs |
useComponentLifecycle |
Track mount/unmount timings and live component lifetime | Full docs |
useMemoProfiling |
Profile useMemo cache hits/misses and recomputation costs |
Full docs |
useWebVitals |
Live Core Web Vitals (LCP, CLS, INP, FCP, TTFB) as React state | Full docs |
useDebouncedState |
Debounced useState with render-skip profiling counters |
Full docs |
useThrottledState |
Throttled useState with dropped-update profiling counters |
Full docs |
useIntersectionObserver |
Lazy-loading visibility state plus first-visible and total-visible metrics | Full docs |
See the docs overview for a complete reference.
import {
useRenderTracker,
useRenderBudget,
usePerformanceMark,
useComponentLifecycle,
useMemoProfiling,
useWebVitals,
useDebouncedState,
useThrottledState,
useIntersectionObserver,
} from 'react-perf-hooks';
function App() {
// Track re-renders and warn if a component renders more than 10 times
const { count } = useRenderTracker({ userId }, { name: 'App', warnAt: 10 });
// Warn when a render exceeds one frame budget (16ms by default)
useRenderBudget(16, 'App');
// Measure fetch duration with the Performance API
const { mark, measure } = usePerformanceMark('App');
// Track mount time and current lifetime of a component
const { mountedAt, aliveMs } = useComponentLifecycle('App');
// Profile whether this memoized computation is mostly cache HITs or MISSes
const filteredUsers = useMemoProfiling(() => users.filter((u) => u.active), [users], 'ActiveUsers');
// Subscribe to Core Web Vitals and report to analytics
const vitals = useWebVitals({
onMetric: (m) => navigator.sendBeacon('/analytics', JSON.stringify(m)),
});
// Debounce state updates and inspect profiling counters
const [query, setQuery, stats] = useDebouncedState('', 250);
// Throttle high-frequency state while measuring discarded updates
const [pointer, setPointer, pointerStats] = useThrottledState({ x: 0, y: 0 }, 120);
// Track when an element first becomes visible and for how long it stays visible
const { ref, isVisible, metrics } = useIntersectionObserver({ threshold: 0.25 });
return <div>...</div>;
}useDebouncedState demo: docs/demos/useDebouncedStateDemo.tsx
useThrottledState demo: docs/demos/useThrottledStateDemo.tsx
useComponentLifecycle demo: docs/demos/useComponentLifecycleDemo.tsx
useMemoProfiling demo: docs/demos/useMemoProfilingDemo.tsx
useIntersectionObserver demo: docs/demos/useIntersectionObserverDemo.tsx
useRenderBudget demo: docs/demos/useRenderBudgetDemo.tsx
All hooks ship with full type declarations. No @types/* packages needed.
import type {
RenderInfo,
UseRenderTrackerOptions,
UseRenderBudgetOptions,
PerformanceMeasureResult,
UsePerformanceMarkReturn,
ComponentLifecycleInfo,
MemoProfilingStats,
WebVitalMetric,
WebVitalsState,
UseWebVitalsOptions,
VitalRating,
DebouncedStateStats,
UseDebouncedStateReturn,
ThrottledStateStats,
UseThrottledStateOptions,
UseThrottledStateReturn,
IntersectionObserverMetrics,
UseIntersectionObserverReturn,
} from 'react-perf-hooks';Contributions are welcome! Please open an issue first to discuss what you'd like to change.
npm install # Install dependencies
npm test # Run tests in watch mode
npm run test:coverage # Run tests once with coverage
npm run type-check # Type-check
npm run lint # Lint
npm run format # Format with Prettier
npm run build # Build CJS + ESM + .d.tsEach hook lives in its own directory under src/hooks/. To add a new hook:
- Create
src/hooks/useYourHook/index.ts - Add tests in
src/hooks/useYourHook/useYourHook.test.tsx - Export from
src/index.ts - Add a doc in
docs/useYourHook.mdand link it fromdocs/index.md
MIT © Valentyn Yefimov