Skip to content
zenui/react-hooks
v2.1.051 new hooks in this release

Hooks for the parts of React you keep rewriting_

91 typed hooks for state, async data, realtime connections, gestures and browser APIs. Each one is SSR-safe, cleans up after itself and ships with zero dependencies.

$ npm install @zenuilabs/react-hooks
this-page.live
rec 00:00
x ---- y ----
useWindowSize---- × ----

move your pointer anywhere on the page

Delete the effect you wrote last sprint.

Persisting a value sounds like one line of work. In practice it needs a server check, a parse guard, a write effect and a listener for other tabs. The hook does all four, and it is tested in Node, so it never breaks a server render.

30
By hand, lines
6
With the hook, lines
use-theme.ts
import {useEffect, useState} from 'react';

function useTheme() {
  const [theme, setTheme] = useState(() => {
    if (typeof window === 'undefined') return 'light';
    try {
      const raw = window.localStorage.getItem('theme');
      return raw ? JSON.parse(raw) : 'light';
    } catch {
      return 'light';
    }
  });

  useEffect(() => {
    try {
      window.localStorage.setItem('theme', JSON.stringify(theme));
    } catch {}
  }, [theme]);

  useEffect(() => {
    const onStorage = (event: StorageEvent) => {
      if (event.key !== 'theme' || event.newValue === null) return;
      setTheme(JSON.parse(event.newValue));
    };
    window.addEventListener('storage', onStorage);
    return () => window.removeEventListener('storage', onStorage);
  }, []);

  return [theme, setTheme] as const;
}

Where most people start.

All hooks
Events & DOMBasicuseClickOutsideCall a function when the user presses anywhere outside an element. Use it to close menus, popovers and dialogs.StateBasicuseCounterHold a number with stable increment, decrement, set and reset helpers. Optional min, max and step options keep it inside a range, which suits quantity pickers and pagers.PerformanceBasicuseDebounceReturn a copy of a value that only updates after it has stopped changing for a set time. Use it to wait for the user to pause before searching or saving.Async & DataIntermediateuseFetchFetch JSON from a URL and track data, loading and error. It aborts stale requests when the URL changes or the component unmounts, and can refetch on demand.StateIntermediateuseLocalStorageKeep a piece of state in localStorage as JSON, synced across components and browser tabs. Use it for preferences and drafts that should survive a reload.StateIntermediateuseSessionStorageKeep a piece of state in sessionStorage as JSON. The value survives a reload but is cleared when the tab closes, which suits wizard steps and temporary form input.PerformanceIntermediateuseThrottleReturn a copy of a fast-changing value that updates at most once per interval. Use it for scroll positions, pointer coordinates and other values that change many times a second.StateBasicuseToggleHold a boolean with stable helpers to flip it, set it and reset it. Use it for modals, menus and on or off settings.Events & DOMBasicuseWindowSizeTrack the inner width and height of the browser window. Use it for layout decisions that CSS media queries cannot express.

New in 2.1: 51 hooks for harder problems.

See what changed