React 19 ready, emotionally questionable

gReact
Hooks

Hooks for problems nobody should have.

Technically functional React 19 hooks with reasons to exist ranging from “barely defensible” to “please just write the value directly.”

useStateWithoutSetter inaction
const status = useStateWithoutSetter("initial");

// There is no setter.
// status remains "initial".
// React has been involved for no reason.

Bad ideas, accurate naming

Small abstractions with enormous audacity.

Every public hook works. Whether any of them should be called is a separate and much shorter discussion.

💗

React involved

Even values that need no hook can now require one.

Types included

TypeScript can describe every questionable decision precisely.

🦄

No coherent strategy

Constants, browser melodrama, and intervals coexist without explanation.

Tree-shakeable

Your bundler can remove the hooks you were sensible enough not to import.

More indirection, no benefit

React abstractions with an obvious better alternative.

Write 0. Use the value directly. Keep the setter. These are all excellent ways to avoid this package.

Why nobody should switch

  • Several APIs replace one line with one hook call.
  • The jokes are more stable than the product strategy.
  • React was already difficult enough without this.

Read the fine print

Hook documentation

Every public export, including the alternatives you should use instead.

Utility

useInterval(callback, delay)

Runs a callback repeatedly. This one is suspiciously defensible.

Signature

useInterval(callback: () => void, delay: number | null);

Example

const [tick, setTick] = useState(0);
useInterval(() => setTick((n) => n + 1), 1000);
Drama

useDramaticPause(delay?)

Calls pointer inactivity a dramatic pause because “idle” lacked theatre.

Signature

useDramaticPause(delay?: number): boolean;

Example

const dramatic = useDramaticPause(1000);
Drama

useTabJealousy(options?)

Makes a browser tab resent visitors who briefly leave it.

Signature

useTabJealousy(options?: UseTabJealousyOptions): string | null;

Example

const complaint = useTabJealousy();
Excuse

useKeyMashExcuse(options?)

Writes an alibi for a burst of keyboard nonsense.

Signature

useKeyMashExcuse(options?: UseKeyMashExcuseOptions): string | null;

Example

const excuse = useKeyMashExcuse({ threshold: 4 });
Prophecy

useDoomScrollOracle(options?)

Predicts absolutely nothing from how far someone scrolls.

Signature

useDoomScrollOracle(options?: UseDoomScrollOracleOptions): string | null;

Example

const prophecy = useDoomScrollOracle({ distance: 800 });
Applause

useFocusFanfare(options?)

Gives every focus change an entirely silent fanfare.

Signature

useFocusFanfare(options?: UseFocusFanfareOptions): string | null;

Example

const fanfare = useFocusFanfare();
Evidence

useClipboardSuspicion(options?)

Treats every copy event as evidence of an unspecified crime.

Signature

useClipboardSuspicion(options?: UseClipboardSuspicionOptions): string | null;

Example

const suspicion = useClipboardSuspicion();
Regret

useBackButtonRegret(options?)

Judges history traversal without knowing whether it was Back or Forward.

Signature

useBackButtonRegret(options?: UseBackButtonRegretOptions): string | null;

Example

const regret = useBackButtonRegret();
Constant

useZeroZero()

Returns 0 through React. A reasonable person would write 0.

Signature

useZeroZero(): number;

Example

const zero = useZeroZero();
Identity

useSameSame<T>(value)

Returns the value supplied. Using the value directly remains available.

Signature

useSameSame<T>(value: T): T;

Example

const same = useSameSame(value);
State

useStateWithoutSetter<T>(initialValue)

Creates state, discards its setter, and leaves the initial value trapped forever.

Signature

useStateWithoutSetter<T>(initialValue: T): T;

Example

const permanentlyInitial = useStateWithoutSetter("initial");

A reasonable person would use the value directly, or keep the setter. This hook should not exist.

Ref

useRefRef<T>(initialValue)

Stores a stable ref inside another stable ref, doubling the indirection without improving the value.

Signature

useRefRef<T>(initialValue: T): RefObject<RefObject<T>>;

Example

const refRef = useRefRef("unnecessarily deep");
const value = refRef.current.current;

A reasonable person would use useRef(initialValue). This hook should not exist.

Effect

useEffectWithoutEffect()

Schedules a React effect whose entire effect is having no effect.

Signature

useEffectWithoutEffect(): void;

Example

useEffectWithoutEffect();

A reasonable person would do nothing at all. This hook should not exist.

Callback

useCallbackCallback(callback)

Memoizes a function, then memoizes another function whose only job is calling the first one.

Signature

useCallbackCallback<Args extends unknown[], Return>(
  callback: (...args: Args) => Return,
): (...args: Args) => Return;

Example

const greetAgain = useCallbackCallback(
  (name: string) => `Hello ${name}`,
);

A reasonable person would use useCallback once. This hook should not exist.

Constant

useTrueTrue()

Returns true, but only after React has confirmed what was already true.

Signature

useTrueTrue(): boolean;

Example

const stillTrue = useTrueTrue();

A reasonable person would write true. This hook should not exist.

Transition

useTransitionWithoutTransition()

Prepares a React transition, then discards the only function capable of starting it.

Signature

useTransitionWithoutTransition(): boolean;

Example

const isNothingPending = useTransitionWithoutTransition();

A reasonable person would write false. This hook should not exist.

Choice

useEitherWay<T>(value)

Demands a boolean choice, then returns the same value from either branch.

Signature

useEitherWay<T>(value: T): (either: boolean) => T;

Example

const chooseAnswer = useEitherWay("same answer");
const answer = chooseAnswer(false);

A reasonable person would use the value directly. This hook should not exist.

Count

useSelfCount<T>(value)

Puts a value in a collection by itself, then counts the unsurprising single occurrence.

Signature

useSelfCount<T>(value: T): readonly [T, number];

Example

const [answer, occurrences] = useSelfCount("alone");

A reasonable person would write [value, 1]. This hook should not exist.

Callback

useWasteCall()

Calls a callback twice, then throws away the second result with complete precision.

Signature

useWasteCall(): <T>(callback: () => T) => T;

Example

const wasteCall = useWasteCall();
const firstResult = wasteCall(() => calculate());

A reasonable person would call the callback once. This hook should not exist.

State

useSetterWithoutState<T>(initialValue)

Creates React state, throws away its value, and keeps only the means to update something nobody can read.

Signature

useSetterWithoutState<T>(
  initialValue: T,
): Dispatch<SetStateAction<T>>;

Example

const setInvisibleState = useSetterWithoutState("hidden");
setInvisibleState("still hidden");

A reasonable person would keep the state returned by useState, or do nothing. This hook should not exist.

Reducer

useNoChangeReducer<T>(initialValue)

Creates a reducer whose dispatch asks for change and receives the exact same state back.

Signature

useNoChangeReducer<T>(
  initialValue: T,
): readonly [T, DispatchWithoutAction];

Example

const [value, refuseChange] = useNoChangeReducer("unchanged");
refuseChange();

A reasonable person would use the initial value and offer no action. This hook should not exist.

New

useRefThenWrap<T>(value)

Stores a value in a ref, ignores the ref, then wraps the current value in a fresh object.

Signature

useRefThenWrap<T>(value: T): { value: T };

Example

const wrapped = useRefThenWrap("already available");

A reasonable person would write { value }. This hook should not exist.