Rooks
HooksState History & Time Travel

useToggle

Toggles a boolean or applies a custom reducer to another state type.

About

useToggle is a small useReducer wrapper. With no custom reducer it flips a boolean-like value; with a reducer it can model any repeated state transition or dispatch typed actions.

Example

import { useToggle } from "rooks";

export default function Disclosure() {
  const [isOpen, toggle] = useToggle(false);

  return (
    <section>
      <button type="button" aria-expanded={isOpen} onClick={toggle}>
        {isOpen ? "Hide" : "Show"} details
      </button>
      {isOpen && <p>The details are now visible.</p>}
    </section>
  );
}

Custom reducer

import { useToggle } from "rooks";

type Action = "next" | "reset";

export default function ThreeStateControl() {
  const [value, dispatch] = useToggle<number, Action>(0, (current, action) => {
    if (action === "reset") return 0;
    return (current + 1) % 3;
  });

  return (
    <div>
      <p>State: {value}</p>
      <button type="button" onClick={() => dispatch("next")}>
        Next
      </button>
      <button type="button" onClick={() => dispatch("reset")}>
        Reset
      </button>
    </div>
  );
}

Parameters

The hook has three call forms:

  • useToggle() starts at false and returns a no-argument toggle function.
  • useToggle(initialValue) starts at the supplied value and returns a no-argument function that applies JavaScript logical negation. Boolean values are the intended use for this form.
  • useToggle(initialValue, reducer) calls reducer(currentValue, action) for each dispatch and returns a typed React dispatch function.

The initial value is read when the reducer is initialized. Later prop changes do not replace the current state.

Return value

Without a custom reducer, the result is [value, toggle], where toggle(): void negates the current value. With a custom reducer, it is [value, dispatch], where dispatch(action) supplies the reducer's second argument.

Behavior and lifecycle

Transitions follow React reducer semantics and are safe to call repeatedly without reading a possibly stale value from the render that created the callback. The hook creates no effects, subscriptions, or cleanup work.

Compatibility and accessibility

The hook has no browser dependency and can render during SSR. When it controls visibility, expose the state with native semantics or attributes such as aria-expanded; a generic toggle should still have a label that explains what is being changed.

  • useCounter provides named increment, decrement, and reset operations for numeric state.

On this page