npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mirawision/reactive-hooks

v1.1.0

Published

A comprehensive collection of 50+ React hooks for state management, UI interactions, device APIs, async operations, drag & drop, audio/speech, and more. Full TypeScript support with SSR safety.

Downloads

52

Readme

@mirawision/reactive-hooks

A comprehensive collection of 50+ React hooks for state management, UI interactions, device APIs, async operations, drag & drop, audio/speech, and more. Built with full TypeScript support and SSR safety.

Installation

npm install @mirawision/reactive-hooks

or

yarn add @mirawision/reactive-hooks

Usage

Import all hooks

import { useToggle, useLocalStorage, useInput } from '@mirawision/reactive-hooks';

Import individual hooks

import { useToggle } from '@mirawision/reactive-hooks/use-toggle';
import { useLocalStorage } from '@mirawision/reactive-hooks/use-local-storage';

Quick Overview

The library is organized into 7 main categories:

  • State Management (13 hooks): Toggle, lists, pagination, sorting, URL params, infinite scroll
  • Storage & Persistence (3 hooks): Local storage, session storage, cookies
  • UI & DOM Events (13 hooks): Event listeners, gestures, drag & drop, keyboard shortcuts
  • Layout & Viewport (6 hooks): Window size, element size, scroll, media queries
  • Device APIs & Browser State (8 hooks): Geolocation, orientation, speech, audio
  • Async & Timing (10 hooks): Fetch, retry, polling, debounce, throttle, queues
  • Lifecycle & Effects (3 hooks): Mount state, update effects

Hooks by Category

State Management

  • useToggle: Boolean state with toggle functionality
  • useInput: Input field state with event handling
  • useList: Array state with common operations
  • usePrevious: Access previous state value
  • useCheckboxes: Manage collection of checkboxes
  • useSort: Manage sorting field and direction
  • usePagination: Handle pagination with array slicing
  • useNumber: Numeric state with min/max limits and step
  • useIterator: Iterate over arrays or numeric ranges
  • useQueryParams: URL query parameters as state
  • useQueryParam: Single URL parameter as state
  • useInfiniteScroll: Infinite loading with intersection observer

Storage & Persistence

  • useLocalStorage: localStorage state with sync
  • useSessionStorage: sessionStorage state with sync
  • useCookie: Cookie-based state management

UI & DOM Events

  • useEventListener: Safe DOM event subscription
  • useOnClickOutside: Handle clicks outside element
  • useHover: Track element hover state
  • useFocus: Track element focus state
  • useKeyPress: Keyboard event handling
  • useShortcuts: Keyboard shortcuts with modifiers
  • useLongPress: Long press detection for mouse/touch
  • useSwipe: Swipe gesture detection
  • useDrag: Drag functionality with data transfer
  • useDragEvents: Custom drag event handlers
  • useDropZone: File drop zone with filtering
  • useEventOnToggle: Conditional event listeners
  • useWindowScrollLock: Lock window scrolling for modals

Layout & Viewport

  • useWindowSize: Window dimensions with throttle
  • useElementSize: Element dimensions with ResizeObserver
  • useScroll: Scroll position tracking
  • useIntersectionObserver: Element visibility tracking
  • useMediaQuery: CSS media query matching
  • useScreenSize: Responsive window dimensions

Device APIs & Browser State

  • useGeolocation: Device location tracking
  • useDeviceOrientation: Device orientation angles
  • useOnlineStatus: Network connectivity state
  • usePageVisibility: Tab visibility tracking
  • useSpeechSynthesis: Text-to-speech functionality
  • useSystemVoices: Available speech synthesis voices
  • useSpeechRecognition: Speech-to-text functionality
  • useAudio: HTML5 audio playback control

Async & Timing

  • useAsync: Async function state wrapper
  • useAsyncQueue: Sequential task execution
  • useRetry: Retry failed operations
  • usePolling: Periodic async execution
  • useFetch: Fetch wrapper with abort/cache
  • useDebounce: Delay value/function updates
  • useThrottle: Limit update frequency
  • useTimeout: Delayed callback execution
  • useInterval: Repeated callback execution
  • useClock: Timer with controls

Lifecycle & Effects

  • useIsMounted: Component mount state
  • useUpdateEffect: Skip first render effect
  • useFirstMountState: First render detection

Example Usage

State Management

// Toggle state
const [isOpen, toggle] = useToggle(false);

// List operations
const [items, { push, remove, move }] = useList(['a', 'b', 'c']);

// Checkbox collection
const { values, toggle, setAll, allChecked } = useCheckboxes({
  item1: true,
  item2: false
});

// Sorting management
const { field, dir, setField, toggleDir } = useSort('name', 'asc');
const sortedItems = items.sort((a, b) => 
  dir === 'asc' ? a[field].localeCompare(b[field]) : b[field].localeCompare(a[field])
);

// Pagination
const { page, slice, next, prev } = usePagination(items.length, 10);
const pageItems = slice(items);

// Numeric state with limits
const { value, inc, dec } = useNumber(0, { min: 0, max: 100, step: 5 });

// Array/range iteration
const { value, next, hasNext } = useIterator(['a', 'b', 'c'], { loop: true });
const { value: index } = useIterator(5); // Iterates over 0..4

Storage & Persistence

// Local storage with sync
const [value, { set, remove }] = useLocalStorage('key', 'default');

// Cookie management
const [token, setToken, removeToken] = useCookie('auth-token', '', {
  days: 7,
  secure: true
});

Device APIs

// Geolocation tracking
const { coords, error } = useGeolocation({
  enableHighAccuracy: true,
  watch: true
});

// Device orientation
const { alpha, beta, gamma } = useDeviceOrientation();

// Tab visibility
const isVisible = usePageVisibility();
if (!isVisible) {
  pauseVideoPlayback();
}

// Lock window scrolling for modal
function Modal({ isOpen }) {
  useWindowScrollLock(isOpen);
  return isOpen ? <div>Modal content</div> : null;
}

// Global keyboard shortcuts
useShortcuts([
  { combo: 'Ctrl+S', handler: (e) => saveDocument(e) },
  { combo: 'Ctrl+Shift+Z', handler: (e) => redo(e) },
  { combo: 'Meta+K', handler: (e) => openCommandPalette(e) }
]);

// URL query parameters as state
const [params, setParams] = useQueryParams();
const page = params.get('page') || '1';
setParams({ page: '2', sort: 'desc' });

// Single URL parameter
const [page, setPage] = useQueryParam('page');
setPage('3', { replace: true }); // Replace history state

// Infinite scroll
function List() {
  const { ref, loading } = useInfiniteScroll({
    hasMore: items.length < total,
    loadMore: () => fetchNextPage(),
  });

  return (
    <div>
      {items.map(item => <Item key={item.id} {...item} />)}
      <div ref={ref}>{loading ? 'Loading...' : null}</div>
    </div>
  );
}

// Long press detection
function Button() {
  const handlers = useLongPress(() => console.log('long press!'), {
    delay: 500,
    cancelOnMove: true,
  });
  return <button {...handlers}>Press and hold</button>;
}

// Swipe gestures
function Card() {
  const ref = useRef(null);
  const { swiping, dir } = useSwipe(ref, {
    minDistance: 50,
    onSwipe: (dir, info) => console.log(dir, info),
  });
  return <div ref={ref} style={{ opacity: swiping ? 0.5 : 1 }} />;
}

// Drag and drop
function DraggableItem({ id, data }) {
  const ref = useRef(null);
  const { dragging } = useDrag(ref, { id, ...data });
  return (
    <div ref={ref} style={{ opacity: dragging ? 0.5 : 1 }}>
      Draggable Item
    </div>
  );
}

function DropZone() {
  const ref = useRef(null);
  const { over } = useDropZone(ref, {
    onDrop: (files) => console.log('Dropped files:', files),
    multiple: true,
    accept: 'image/*,.pdf'
  });
  return (
    <div ref={ref} style={{ border: over ? '2px dashed blue' : '2px dashed gray' }}>
      Drop files here
    </div>
  );
}

// Custom drag events
function CustomDragArea() {
  const ref = useRef(null);
  useDragEvents(ref, {
    onDragStart: (e) => console.log('Drag started'),
    onDrop: (e) => {
      const data = e.dataTransfer.getData('application/json');
      console.log('Dropped data:', JSON.parse(data));
    }
  });
  return <div ref={ref}>Custom drag area</div>;
}

// Custom drag events
function CustomDragArea() {
  const ref = useRef(null);
  useDragEvents(ref, {
    onDragStart: (e) => console.log('Drag started'),
    onDrop: (e) => {
      const data = e.dataTransfer.getData('application/json');
      console.log('Dropped data:', JSON.parse(data));
    }
  });
  return <div ref={ref}>Custom drag area</div>;
}

// Text-to-speech
function TextReader() {
  const { speak, speaking, pause, resume } = useSpeechSynthesis();
  const voices = useSystemVoices();
  return (
    <div>
      <button onClick={() => speak('Hello world', { rate: 1.5 })}>
        {speaking ? 'Speaking...' : 'Speak'}
      </button>
      <select>{voices.map(v => <option key={v.name}>{v.name}</option>)}</select>
    </div>
  );
}

// Speech recognition
function VoiceInput() {
  const { transcript, listening, start, stop } = useSpeechRecognition({
    continuous: true,
    interimResults: true,
  });
  return (
    <div>
      <button onClick={listening ? stop : start}>
        {listening ? 'Stop' : 'Start'} listening
      </button>
      <p>{transcript}</p>
    </div>
  );
}

// Audio player
function AudioPlayer() {
  const { audioRef, playing, play, pause, currentTime, duration, volume, setVolume } = useAudio('/audio.mp3');
  
  return (
    <div>
      <audio ref={audioRef} />
      <button onClick={playing ? pause : play}>
        {playing ? 'Pause' : 'Play'}
      </button>
      <input
        type="range"
        min="0"
        max={duration}
        value={currentTime}
        onChange={(e) => seek(Number(e.target.value))}
      />
      <input
        type="range"
        min="0"
        max="1"
        step="0.1"
        value={volume}
        onChange={(e) => setVolume(Number(e.target.value))}
      />
      <span>{Math.floor(currentTime)}s / {Math.floor(duration)}s</span>
    </div>
  );
}

Async Operations

// Sequential task queue
const queue = useAsyncQueue();
await queue.enqueue(() => saveData());

// Retry with backoff
const { run, error } = useRetry(fetchData, {
  retries: 3,
  delayMs: 1000
});

// Debounced search
const debouncedQuery = useDebounce(searchQuery, 300);

Features

  • 50+ Hooks: Comprehensive coverage of React development needs
  • Type-safe: Full TypeScript support with detailed type definitions
  • Tree-shakeable: Import only what you need, reduce bundle size
  • Well-tested: Extensive test coverage for all hooks
  • SSR-safe: Server-side rendering support with graceful degradation
  • Lightweight: Minimal dependencies, optimized for performance
  • React 16.8+ compatible: Modern hooks API with backward compatibility (supports React 19)
  • Cross-platform: Works across browsers, devices, and platforms
  • Accessibility: Built with accessibility best practices in mind
  • Performance: Optimized for performance with proper cleanup and memoization

Library Statistics

  • Total Hooks: 56 hooks across 7 categories
  • TypeScript Coverage: 100% with full type definitions
  • Test Coverage: Comprehensive tests for all hooks
  • Bundle Size: Tree-shakeable, import only what you need
  • Browser Support: Modern browsers with SSR safety
  • React Versions: 16.8+ (hooks support, including React 19)

API Reference

Each hook is documented with TypeScript types and JSDoc comments. For detailed API documentation:

  1. See the TypeScript definitions
  2. Check individual hook files
  3. Refer to test files for usage examples

Contributing

Contributions are welcome! Please read our contributing guidelines for details.