Small, strict, modern React hooks — the ones you end up writing in every project, packaged the right way.
Status: bootstrapping — the packaging, CI, docs, and release pipeline are in place; the hook surface is still one hook and growing. As much a showcase of hook-packaging best practices as a hooks library.
pnpm add @goodnight-dev/react-hooks
Requires React >=19.
// 1. Barrel — everything from one entry point.
import { useLocalStorage, useTheme } from '@goodnight-dev/react-hooks';
// 2. Subpath — smallest possible import, no barrel involved at all.
import { useTheme } from '@goodnight-dev/react-hooks/useTheme';
import { useLocalStorage } from '@goodnight-dev/react-hooks/useLocalStorage';
Both are fully typed, ESM-only, and tree-shakable.
| Hook | Description |
|---|---|
useTheme() |
Reads the OS prefers-color-scheme, live-updating on change. |
useLocalStorage(key, initial) |
Reads and writes a JSON-serializable value in localStorage, syncing across tabs. |
import { useLocalStorage, useTheme } from '@goodnight-dev/react-hooks';
// Module scope: created once when this file loads, never re-allocated on
// render, so there's nothing to memoize.
const defaultSettings = { seen: false };
function App() {
const { theme, isDarkMode } = useTheme();
const [settings, setSettings] = useLocalStorage(
`users-${userId}`,
defaultSettings,
);
if (theme === undefined) return null; // avoid a flash of the wrong theme
return (
<div data-theme={theme}>
{isDarkMode ? '🌙' : '☀️'}
<button onClick={() => setSettings((s) => ({ ...s, seen: true }))}>
Dismiss
</button>
</div>
);
}
See src/use-theme.md and
src/use-local-storage.md for the design
rationale behind each.
>=19 peer dependencyuseSyncExternalStore
where it subscribes to something outside ReactstrictTypeChecked, eslint-plugin-react-hooks, Prettier)This repo is opinionated about how the code is written. See CONTRIBUTING.md for the full rationale; in short:
useSyncExternalStore, never useEffect +
useState. A server render never guesses a client-only value.node_modules but our own code — React itself is a peer
dependency.*.md (repo-only, academic)
explaining alternative implementations and why we chose ours — e.g.
use-theme.md.This is a pnpm project. Requires Node >=22.
pnpm install # install dependencies
pnpm build # build the package (tsdown)
pnpm test # run the test suite (vitest)
pnpm typecheck # tsc --noEmit
pnpm lint # eslint
pnpm format # prettier --check
pnpm check # everything: format, lint, build, typecheck, test, exports
pnpm docs:build # generate the API docs site (TypeDoc)
docs/ — recipes (adding a hook, cutting a release) and
architecture decision records.MIT © Ian Goodnight