A comprehensive collection of production-ready React hooks for modern web applications. Features type-safe implementations, extensive testing, and zero dependencies. Includes hooks for state management, browser APIs, user interactions, and development uti
npm install @qazuor/react-hooksA collection of high-quality, fully tested React hooks for common use cases. Written in TypeScript with comprehensive documentation and examples.
- Qazuor React Custom Hooks
- Table of Contents
- Features
- Installation
- Available Hooks
- State Management
- useBoolean
- useToggle
- useQueue
- Side Effects
- useTimeout
- useInterval
- useHandledInterval
- useDebounce
- Browser APIs
- useLocalStorage
- useSessionStorage
- useCopyToClipboard
- useMediaQuery
- useNetworkState
- useVisibilityChange
- useWindowWidth
- User Interaction
- useClickOutside
- useIdleness
- usePageLeave
- useLockBodyScroll
- useMeasure
- Development
- useLogger
- TypeScript Support
- Browser Support
- Contributing
- License
- Author
- 📦 20+ Custom Hooks
- 🔒 Type-safe with TypeScript
- 📚 Comprehensive documentation
- ✅ Fully tested
- 🎯 Zero dependencies
- 🌳 Tree-shakeable
- 💻 SSR compatible
``bashUsing npm
npm install @qazuor/react-hooks
Available Hooks
$3
#### useBoolean
Manages a boolean state with convenient methods.
`tsx
import { useBoolean } from '@qazuor/react-hooks';function Modal() {
const { value: isOpen, setTrue: open, setFalse: close } = useBoolean(false);
return (
<>
{isOpen && (
Modal Content
)}
>
);
}
`#### useToggle
Manages a toggleable boolean state with persistence options.
`tsx
import { useToggle } from '@qazuor/react-hooks';function ThemeToggle() {
const { value: isDark, toggle } = useToggle({
initialValue: false,
persist: true,
storageKey: 'theme-preference'
});
return (
);
}
`#### useQueue
Implements a FIFO queue with state management.
`tsx
import { useQueue } from '@qazuor/react-hooks';function TaskQueue() {
const { enqueue, dequeue, peek, size, isEmpty } = useQueue();
return (
Next task: {peek() || 'No tasks'}
Queue size: {size}
);
}
`$3
#### useTimeout
Execute a callback after a delay with control methods.
`tsx
import { useTimeout } from '@qazuor/react-hooks';function AutoDismiss() {
const [visible, setVisible] = useState(true);
const { isPending, reset } = useTimeout({
callback: () => setVisible(false),
delay: 3000
});
return visible && (
I will disappear in 3 seconds!
);
}
`#### useInterval
Execute a callback at regular intervals with pause/resume functionality.
`tsx
import { useInterval } from '@qazuor/react-hooks';function Counter() {
const [count, setCount] = useState(0);
const { isRunning, start, pause } = useInterval({
callback: () => setCount(c => c + 1),
delay: 1000
});
return (
Count: {count}
);
}
`#### useHandledInterval
Enhanced interval with random delay options and more control.
`tsx
import { useHandledInterval } from '@qazuor/react-hooks';function RandomTimer() {
const [count, setCount] = useState(0);
const { isRunning, start, pause, reset } = useHandledInterval({
callback: () => setCount(c => c + 1),
delay: 1000,
random: true,
minDelay: 500
});
return (
Random intervals count: {count}
);
}
`#### useDebounce
Debounce a value with configurable delay.
`tsx
import { useDebounce } from '@qazuor/react-hooks';function SearchInput() {
const [value, setValue] = useState('');
const debouncedValue = useDebounce(value, 500);
useEffect(() => {
// API call with debouncedValue
console.log('Searching:', debouncedValue);
}, [debouncedValue]);
return (
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Search..."
/>
);
}
`$3
#### useLocalStorage
Persist state in localStorage with type safety.
`tsx
import { useLocalStorage } from '@qazuor/react-hooks';function UserPreferences() {
const [preferences, setPreferences] = useLocalStorage('user-prefs', {
theme: 'light',
fontSize: 16
});
return (
onClick={() => setPreferences(p => ({ ...p, theme: p.theme === 'light' ? 'dark' : 'light' }))}
type="button"
>
Toggle Theme
value={preferences.fontSize}
onChange={(e) => setPreferences(p => ({ ...p, fontSize: Number(e.target.value) }))}
>
);
}
`#### useSessionStorage
Persist state in sessionStorage.
`tsx
import { useSessionStorage } from '@qazuor/react-hooks';function FormWithAutosave() {
const [formData, setFormData] = useSessionStorage('form-draft', {
title: '',
content: ''
});
return (
);
}
`#### useCopyToClipboard
Copy text to clipboard with status feedback.
`tsx
import { useCopyToClipboard } from '@qazuor/react-hooks';function ShareButton() {
const { copy, copied, error } = useCopyToClipboard();
const url = window.location.href;
return (
onClick={() => copy(url)}
type="button"
className={copied ? 'success' : error ? 'error' : ''}
>
{copied ? 'Copied!' : error ? 'Failed to copy' : 'Copy URL'}
);
}
`#### useMediaQuery
React to media query changes.
`tsx
import { useMediaQuery } from '@qazuor/react-hooks';function ResponsiveLayout() {
const isMobile = useMediaQuery('(max-width: 768px)');
const prefersDark = useMediaQuery('(prefers-color-scheme: dark)');
return (
layout ${isMobile ? 'mobile' : 'desktop'} ${prefersDark ? 'dark' : 'light'}}>
Current layout: {isMobile ? 'Mobile' : 'Desktop'}
Theme preference: {prefersDark ? 'Dark' : 'Light'}
);
}
`#### useNetworkState
Track network connectivity status.
`tsx
import { useNetworkState } from '@qazuor/react-hooks';function NetworkIndicator() {
const { online, type, rtt } = useNetworkState();
return (
status-dot ${online ? 'online' : 'offline'}} />
{online && (
<>
Connection: {type}
Latency: {rtt}ms
>
)}
);
}
`#### useVisibilityChange
Track document visibility state.
`tsx
import { useVisibilityChange } from '@qazuor/react-hooks';function VideoPlayer() {
const videoRef = useRef(null);
const { isVisible } = useVisibilityChange({
onHidden: () => videoRef.current?.pause(),
onVisible: () => videoRef.current?.play()
});
return (
Video is {isVisible ? 'visible' : 'hidden'}
);
}
`#### useWindowWidth
Track window width with debouncing.
`tsx
import { useWindowWidth } from '@qazuor/react-hooks';function ResponsiveComponent() {
const { width } = useWindowWidth({
debounceDelay: 250,
onChange: (w) => console.log(
Window width changed to ${w}px)
}); return (
Window width: {width}px
{width > 1024 ? (
Desktop View
) : width > 768 ? (
Tablet View
) : (
Mobile View
)}
);
}
`$3
#### useClickOutside
Detect clicks outside an element.
`tsx
import { useClickOutside } from '@qazuor/react-hooks';function Dropdown() {
const [isOpen, setIsOpen] = useState(false);
const ref = useRef(null);
useClickOutside(ref, () => setIsOpen(false));
return (
{isOpen && (
- Option 1
- Option 2
)}
);
}
`#### useIdleness
Track user idle state.
`tsx
import { useIdleness } from '@qazuor/react-hooks';function IdleMonitor() {
const { isIdle, reset } = useIdleness({
timeout: 5000,
onIdleChange: (idle) => {
if (idle) {
console.log('User is idle');
} else {
console.log('User is active');
}
}
});
return (
User is currently {isIdle ? 'idle' : 'active'}
);
}
`#### usePageLeave
Detect when user attempts to leave page.
`tsx
import { usePageLeave } from '@qazuor/react-hooks';function ExitIntent() {
const { hasLeft } = usePageLeave({
onLeave: () => console.log('Mouse left the page'),
threshold: 10
});
return hasLeft && (
Wait! Don't leave yet...
Would you like to subscribe to our newsletter?
);
}
`#### useLockBodyScroll
Prevent body scrolling.
`tsx
import { useLockBodyScroll } from '@qazuor/react-hooks';function Modal({ isOpen }: { isOpen: boolean }) {
const { isLocked, lock, unlock } = useLockBodyScroll({
lockImmediately: isOpen,
preservePosition: true
});
useEffect(() => {
if (isOpen) {
lock();
} else {
unlock();
}
}, [isOpen, lock, unlock]);
return isOpen && (
Modal Content
Body scroll is {isLocked ? 'locked' : 'unlocked'}
);
}
`#### useMeasure
Measure DOM elements.
`tsx
import { useMeasure } from '@qazuor/react-hooks';function ResizableBox() {
const { ref, size } = useMeasure();
return (
ref={ref}
style={{
resize: 'both',
overflow: 'auto',
minWidth: '100px',
minHeight: '100px',
border: '1px solid black'
}}
>
Width: {size.width}px
Height: {size.height}px
);
}
`$3
#### useLogger
Debug values with console logging.
`tsx
import { useLogger } from '@qazuor/react-hooks';function DebugComponent() {
const [count, setCount] = useState(0);
useLogger('Counter Value', count, {
level: 'info',
timestamp: true,
formatter: (label, value) =>
${label}: ${value} (${new Date().toISOString()})
}); return (
);
}
`TypeScript Support
All hooks are written in TypeScript and include comprehensive type definitions. Generic types are used where appropriate to ensure type safety.
`tsx
interface UserPreferences {
theme: 'light' | 'dark';
fontSize: number;
}// Type-safe localStorage hook
const [preferences, setPreferences] = useLocalStorage('prefs', {
theme: 'light',
fontSize: 16
});
// TypeScript knows the correct types
preferences.theme; // 'light' | 'dark'
preferences.fontSize; // number
``The library supports all modern browsers. Some hooks may require specific browser features - check individual hook documentation for details.
Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
This project is licensed under the MIT License - see the LICENSE file for details.
Leandro Asrilevich (@qazuor)