8000 GitHub - qazuor/reactCustomHooks: React Custom Hooks
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

qazuor/reactCustomHooks

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

53 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Qazuor React Custom Hooks

React Custom Hooks Library Logo
npm version npm downloads License: MIT TypeScript React

A collection of high-quality, fully tested React hooks for common use cases. Written in TypeScript with comprehensive documentation and examples.

Table of Contents

Features

  • 📦 20+ Custom Hooks
  • đź”’ Type-safe with TypeScript
  • 📚 Comprehensive documentation
  • âś… Fully tested
  • 🎯 Zero dependencies
  • 🌳 Tree-shakeable
  • đź’» SSR compatible

Installation

# Using npm
npm install @qazuor/react-hooks

# Using yarn
yarn add @qazuor/react-hooks

# Using pnpm
pnpm add @qazuor/react-hooks

Available Hooks

State Management

useBoolean

Manages a boolean state with convenient methods.

import { useBoolean } from '@qazuor/react-hooks';

function Modal() {
    const { value: isOpen, setTrue: open, setFalse: close } = useBoolean(false);

    return (
        <>
            <button onClick={open} type="button">Open Modal</button>
            {isOpen && (
                <div className="modal">
                    <button onClick={close} type="button">Close</button>
                    <h1>Modal Content</h1>
                </div>
            )}
        </>
    );
}

useToggle

Manages a toggleable boolean state with persistence options.

import { useToggle } from '@qazuor/react-hooks';

function ThemeToggle() {
    const { value: isDark, toggle } = useToggle({
        initialValue: false,
        persist: true,
        storageKey: 'theme-preference'
    });

    return (
        <button onClick={toggle} type="button">
            Current theme: {isDark ? 'Dark' : 'Light'}
        </button>
    );
}

useQueue

Implements a FIFO queue with state management.

import { useQueue } from '@qazuor/react-hooks';

function TaskQueue() {
    const { enqueue, dequeue, peek, size, isEmpty } = useQueue<string>();

    return (
        <div>
            <button onClick={() => enqueue(`Task ${size + 1}`)} type="button">
                Add Task
            </button>
            <button onClick={dequeue} disabled={isEmpty} type="button">
                Process Next
            </button>
            <p>Next task: {peek() || 'No tasks'}</p>
            <p>Queue size: {size}</p>
        </div>
    );
}

Side Effects

useTimeout

Execute a callback after a delay with control methods.

import { useTimeout } from '@qazuor/react-hooks';

function AutoDismiss() {
    const [visible, setVisible] = useState(true);
    const { isPending, reset } = useTimeout({
        callback: () => setVisible(false),
        delay: 3000
    });

    return visible && (
        <div>
            <p>I will disappear in 3 seconds!</p>
            <button onClick={reset} type="button">Reset Timer</button>
        </div>
    );
}

useInterval

Execute a callback at regular intervals with pause/resume functionality.

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 (
        <div>
            <p>Count: {count}</p>
            <button onClick={isRunning ? pause : start} type="button">
                {isRunning ? 'Pause' : 'Start'}
            </button>
        </div>
    );
}

useHandledInterval

Enhanced interval with random delay options and more control.

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 (
        <div>
            <p>Random intervals count: {count}</p>
            <button onClick={isRunning ? pause : start} type="button">
                {isRunning ? 'Pause' : 'Start'}
            </button>
            <button onClick={reset} type="button">Reset</button>
        </div>
    );
}

useDebounce

Debounce a value with configurable delay.

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 (
        <input
            value={value}
            onChange={(e) => setValue(e.target.value)}
            placeholder="Search..."
        />
    );
}

Browser APIs

useLocalStorage

Persist state in localStorage with type safety.

import { useLocalStorage } from '@qazuor/react-hooks';

function UserPreferences() {
    const [preferences, setPreferences] = useLocalStorage('user-prefs', {
        theme: 'light',
        fontSize: 16
    });

    return (
        <div>
            <button
                onClick={() => setPreferences(p => ({ ...p, theme: p.theme === 'light' ? 'dark' : 'light' }))}
                type="button"
            >
                Toggle Theme
            </button>
            <select
                value={preferences.fontSize}
                onChange={(e) => setPreferences(p => ({ ...p, fontSize: Number(e.target.value) }))}
            >
                <option value="14">Small</option>
                <option value="16">Medium</option>
                <option value="18">Large</option>
            </select>
        </div>
    );
}

useSessionStorage

Persist state in sessionStorage.

import { useSessionStorage } from '@qazuor/react-hooks';

function FormWithAutosave() {
    const [formData, setFormData] = useSessionStorage('form-draft', {
        title: '',
        content: ''
    });

    return (
        <form>
            <input
                value={formData.title}
                onChange={(e) => setFormData(prev => ({ ...prev, title: e.target.value }))}
                placeholder="Title"
            />
            <textarea
                value={formData.content}
                onChange={(e) => setFormData(prev => ({ ...prev, content: e.target.value }))}
                placeholder="Content"
            />
        </form>
    );
}

useCopyToClipboard

Copy text to clipboard with status feedback.

import { useCopyToClipboard } from '@qazuor/react-hooks';

function ShareButton() {
    const { copy, copied, error } = useCopyToClipboard();
    const url = window.location.href;

    return (
        <button
            onClick={() => copy(url)}
            type="button"
            className={copied ? 'success' : error ? 'error' : ''}
        >
            {copied ? 'Copied!' : error ? 'Failed to copy' : 'Copy URL'}
        </button>
    );
}

useMediaQuery

React to media query changes.

import { useMediaQuery } from '@qazuor/react-hooks';

function ResponsiveLayout() {
    const isMobile = useMediaQuery('(max-width: 768px)');
    const prefersDark = useMediaQuery('(prefers-color-scheme: dark)');

    return (
        <div className={`layout ${isMobile ? 'mobile' : 'desktop'} ${prefersDark ? 'dark' : 'light'}`}>
            <p>Current layout: {isMobile ? 'Mobile' : 'Desktop'}</p>
            <p>Theme preference: {prefersDark ? 'Dark' : 'Light'}</p>
        </div>
    );
}

useNetworkState

Track network connectivity status.

import { useNetworkState } from '@qazuor/react-hooks';

function NetworkIndicator() {
    const { online, type, rtt } = useNetworkState();

    return (
        <div>
            <div className={`status-dot ${online ? 'online' : 'offline'}`} />
            {online && (
                <>
                    <p>Connection: {type}</p>
                    <p>Latency: {rtt}ms</p>
                </>
            )}
        </div>
    );
}

useVisibilityChange

Track document visibility state.

import { useVisibilityChange } from '@qazuor/react-hooks';

function VideoPlayer() {
    const videoRef = useRef<HTMLVideoElement>(null);
    const { isVisible } = useVisibilityChange({
        onHidden: () => videoRef.current?.pause(),
        onVisible: () => videoRef.current?.play()
    });

    return (
        <div>
            <video ref={videoRef} />
            <p>Video is {isVisible ? 'visible' : 'hidden'}</p>
        </div>
    );
}

useWindowWidth

Track window width with debouncing.

import { useWindowWidth } from '@qazuor/react-hooks';

function ResponsiveComponent() {
    const { width } = useWindowWidth({
        debounceDelay: 250,
        onChange: (w) => console.log(`Window width changed to ${w}px`)
    });

    return (
        <div>
            <p>Window width: {width}px</p>
            {width > 1024 ? (
                <h1>Desktop View</h1>
            ) : width > 768 ? (
                <h2>Tablet View</h2>
            ) : (
                <h3>Mobile View</h3>
            )}
        </div>
    );
}

User Interaction

useClickOutside

Detect clicks outside an element.

import { useClickOutside } from '@qazuor/react-hooks';

function Dropdown() {
    const [isOpen, setIsOpen] = useState(false);
    const ref = useRef(null);

    useClickOutside(ref, () => setIsOpen(false));

    return (
        <div ref={ref}>
            <button onClick={() => setIsOpen(true)} type="button">
                Toggle Dropdown
            </button>
            {isOpen && (
                <ul className="dropdown-menu">
                    <li>Option 1</li>
                    <li>Option 2</li>
                </ul>
            )}
        </div>
    );
}

useIdleness

Track user idle state.

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 (
        <div>
            <p>User is currently {isIdle ? 'idle' : 'active'}</p>
            <button onClick={reset} type="button">Reset Idle Timer</button>
        </div>
    );
}

usePageLeave

Detect when user attempts to leave page.

import { usePageLeave } from '@qazuor/react-hooks';

function ExitIntent() {
    const { hasLeft } = usePageLeave({
        onLeave: () => console.log('Mouse left the page'),
        threshold: 10
    });

    return hasLeft && (
        <div className="exit-popup">
            <h2>Wait! Don't leave yet...</h2>
            <p>Would you like to subscribe to our newsletter?</p>
        </div>
    );
}

useLockBodyScroll

Prevent body scrolling.

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 && (
        <div className="modal">
            <h2>Modal Content</h2>
            <p>Body scroll is {isLocked ? 'locked' : 'unlocked'}</p>
        </div>
    );
}

useMeasure

Measure DOM elements.

import { useMeasure } from '@qazuor/react-hooks';

function ResizableBox() {
    const { ref, size } = useMeasure();

    return (
        <div
            ref={ref}
            style={{
                resize: 'both',
                overflow: 'auto',
                minWidth: '100px',
                minHeight: '100px',
                border: '1px solid black'
            }}
        >
            <p>Width: {size.width}px</p>
            <p>Height: {size.height}px</p>
        </div>
    );
}

Development

useLogger

Debug values with console logging.

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 (
        <button onClick={() => setCount(c => c + 1)} type="button">
            Increment ({count})
        </button>
    );
}

TypeScript Support

All hooks are written in TypeScript and include comprehensive type definitions. Generic types are used where appropriate to ensure type safety.

interface UserPreferences {
    theme: 'light' | 'dark';
    fontSize: number;
}

// Type-safe localStorage hook
const [preferences, setPreferences] = useLocalStorage<UserPreferences>('prefs', {
    theme: 'light',
    fontSize: 16
});

// TypeScript knows the correct types
preferences.theme; // 'light' | 'dark'
preferences.fontSize; // number

Browser Support

The library supports all modern browsers. Some hooks may require specific browser features - check individual hook documentation for details.

Contributing

Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Author

Leandro Asrilevich (@qazuor)

About

React Custom Hooks

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published
0