Skip to content

useHotkeyRegistrations causes React setState-in-render warning with useHotkey #113

@OliverJAsh

Description

@OliverJAsh

Description

When one component subscribes to hotkey registrations using useHotkeyRegistrations() and another component registers a hotkey using useHotkey(), React logs a warning:

Cannot update a component (`ShortcutsBar`) while rendering a different component (`HotkeyOwner`). To locate the bad setState() call inside `HotkeyOwner`, follow the stack trace as described in https://react.dev/link/setstate-in-render

This appears to happen because useHotkey() updates registration options during render after a hotkey has been registered, and useHotkeyRegistrations() subscribes another component to the same registration store.

Reproduction

Reduced repro repo:

https://github.com/OliverJAsh/tanstack-hotkeys-render-warning-repro

Steps:

git clone https://github.com/OliverJAsh/tanstack-hotkeys-render-warning-repro.git
cd tanstack-hotkeys-render-warning-repro
npm install
npm run dev

Open the page in a browser.

Expected Behavior

Using useHotkeyRegistrations() to render a shortcuts bar should not trigger React warnings when hotkeys are registered or updated.

Actual Behavior

React logs the setState-in-render warning during initial page load:

Cannot update a component (`ShortcutsBar`) while rendering a different component (`HotkeyOwner`).

Suspected Cause

In useHotkey, callback/options are synced during render:

if (registrationRef.current?.isActive) {
  registrationRef.current.callback = callback
  registrationRef.current.setOptions(optionsWithoutTarget)
}

setOptions(...) updates the global hotkey registration store. Since ShortcutsBar is subscribed through useHotkeyRegistrations(), React sees this as updating ShortcutsBar while rendering HotkeyOwner.

Environment

  • @tanstack/react-hotkeys: 0.10.0
  • React: latest / React 19
  • Browser: Chromium
  • Build tool: Vite

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions