Skip to content

Repository files navigation

hookli — React hooks, ready to use

hookli

A tiny, typed collection of the React hooks you reach for every day.
Every hook you rewrite — typed, SSR-safe, zero dependencies.

npm version npm downloads per month total npm downloads minzipped size GitHub stars Sponsor license

zero dependencies TypeScript SSR-safe tree-shakable ESM + CJS 65 hooks

Browse the hooks →

Created by Saif Mohamed · ISC licensed

🚀 Install

npm i hookli
# or
yarn add hookli
# or
pnpm add hookli

Peer dependency: React >=18.

💫 Introduction

hookli is a React hooks library, written in TypeScript and ready to ship. It gives you a small, dependency-free set of the hooks you reach for in almost every project — debounce, localStorage wrappers, outside-click listeners, and the rest — so you stop rewriting the same utilities for the hundredth time.

What sets hookli apart from similar libraries (including usehooks-ts):

  • Zero runtime dependencies — not just "small deps," literally none besides React.
  • SSR-safe by convention — every hook guards browser APIs; safe in Next.js and Remix.
  • Manifest-driven docs — README, hook count, and the docs site all derive from one source of truth.
  • Live demos on the real package — the docs import from npm, not a fork or snapshot.
  • Every hook tested — colocated vitest tests and a CI gate on every PR.

The library is designed to be as minimal as possible. It is fully tree-shakable (via the ESM build), meaning you only ship the hooks you import and the rest is removed from your bundle — the cost of adding hookli is negligible. Every hook is typed and SSR-safe, so it drops straight into Next.js / Remix.

Usage

import { useLocalStorage } from "hookli";

function Component() {
  const { value, setStoredValue } = useLocalStorage("my-key", 0);

  // ...
}

🪝 Available hooks

📚 Full docs with a page per hook and live demos: https://hookli.vercel.app/docs

  • useToggle — Boolean state with toggle and explicit set.
  • useForm — Controlled form state with one change handler.
  • useLocalStorage — State persisted to localStorage.
  • useLocalStorageWithExpiry — Persisted state with a TTL.
  • useSessionStorage — useState backed by sessionStorage, synced across tabs.
  • useReadLocalStorage — Read a localStorage key without writing it, reactively.
  • useDarkMode — Dark-mode boolean with toggle.
  • useTernaryDarkMode — Three-state dark mode — system, dark or light — persisted.
  • useBoolean — Boolean state with setTrue, setFalse, toggle and set.
  • useCounter — Numeric counter with increment, decrement and reset.
  • useStep — 1-indexed step counter for wizards and steppers.
  • useCountdown — Self-stopping countdown or count-up timer.
  • useMap — Manage a Map as immutable React state.
  • useDebounce — Debounces a changing value.
  • useDebounceValue — State whose debounced copy updates after a pause.
  • useDebounceCallback — Debounces a callback, with cancel, flush and isPending.
  • useInterval — Runs a callback on a fixed interval; pause by passing null.
  • useTimeout — Runs a callback once after a delay; cancel by passing null.
  • useIsomorphicLayoutEffect — useLayoutEffect on the client, useEffect on the server.
  • useEventCallback — A stable callback that always calls the latest closure.
  • useUnmount — Runs a cleanup function once, when the component unmounts.
  • useIsClient — Reports false on the server and true after hydration.
  • useIsMounted — A stable getter for whether the component is still mounted.
  • useDocumentTitle — Keeps document.title in sync with a value, SSR-safe.
  • useEventListener — Subscribe to a window, document or element event with cleanup.
  • useClickOutside — Runs a callback on outside click.
  • useMousePosition — Cursor coordinates within an element.
  • useInfiniteScroll — Triggers loading near the scroll end.
  • useExpandableText — Collapse long text by a character and/or line budget with a show-more toggle.
  • useHover — Tracks whether the pointer is hovering an element.
  • useIntersectionObserver — Observe an element's viewport intersection reactively.
  • useResizeObserver — Measure an element's size reactively via ResizeObserver.
  • useScrollLock — Lock and restore scrolling on the body or an element.
  • useClickAnyWhere — Run a handler on every click anywhere in the document.
  • useMediaQuery — Tracks whether a CSS media query currently matches.
  • useScreen — Tracks window.screen, refreshing it on every resize.
  • useWindowSize — Tracks the viewport's { width, height }, updated on resize.
  • useCopyToClipboard — Copy text to the clipboard, tracking the last copied value.
  • useScript — Load an external script and report its load status.
  • useFetch — Declarative fetch with loading and error status.
  • useGeoLocation — Browser geolocation state.
  • usePrevious — Track a value from the previous render.
  • useList — Array state with push, insert, update, remove, and clear helpers.
  • useSet — Set state with add, remove, toggle, has, and clear helpers.
  • useThrottle — Throttle a fast-changing value to at most one update per interval.
  • useUpdateEffect — A useEffect that skips the initial mount and runs only on updates.
  • useEffectOnce — Run an effect exactly once, on mount.
  • useKeyPress — Track whether a specific key is currently held down.
  • useWindowScroll — Track the window scroll position reactively.
  • useAsync — Run an async function and track its loading, error, and value state.
  • useMutation — Run an async write action on demand and track status, data, and error.
  • usePagination — Page, page size, total pages, navigation helpers, and the current item range.
  • useNetworkState — Track online/offline status and connection details.
  • usePageVisibility — Track whether the page/tab is currently visible.
  • useIdle — Detect user inactivity after a configurable threshold.
  • useQueue — FIFO queue state with add, remove, clear, and first/last/size.
  • useDefault — useState that falls back to a default when the value is nullish.
  • useRafState — useState whose updates are batched to the next animation frame.
  • useDeepCompareEffect — useEffect that compares dependencies by deep structural equality.
  • useTextSelection — Track the text the user has currently selected on the page.
  • useLongPress — Detect a long press (mouse or touch) via spreadable handlers.
  • useHotkeys — Bind a keyboard shortcut combo (e.g. ctrl+k) to a callback.
  • useFullscreen — Control the Fullscreen API for an element and track its state.
  • useBattery — Read device battery level and charging state (where supported).
  • usePermission — Query a Permissions API permission and track its state.

🧪 TypeScript

Every hook ships its own declarations — no @types/hookli needed. Data hooks are generic, so inference flows through:

const { data } = useFetch<Product[]>("/api/products"); // data: Product[] | null
const debounced = useDebounce(query, 300); // debounced: typeof query

💖 Support hookli

hookli is free and open source, built and maintained in the open. If it saves you time:

Every star and sponsorship genuinely helps keep this going. Thank you! 🙏

🤝 Contributing

Contributions of any size are welcome — see CONTRIBUTING.md. In short: each hook lives in its own folder under src/hooks/use-<name>/ (hook + colocated vitest test + barrel), keep it SSR-safe, and make sure bash ralph/check.sh (typecheck + tests + build) is green.

📄 License

ISC © Saif Mohamed

About

A tiny, typed collection of the React hooks you reach for every day. Zero deps · SSR-safe · ESM + CJS · fully tree-shakable. npm i hookli

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages