Overview
You can control when hotkeys are active using the enabled option. This is useful for disabling shortcuts in certain UI states or based on user permissions.
Using the Enabled Option
Boolean Value
The simplest way to disable a hotkey is with a boolean:
import { useHotkeys } from 'react-hotkeys-hook'
import { useState } from 'react'
function EditableContent() {
const [isEditing, setIsEditing] = useState(false)
// Only active when NOT editing
useHotkeys('e', () => setIsEditing(true), {
enabled: !isEditing,
})
// Only active when editing
useHotkeys('escape', () => setIsEditing(false), {
enabled: isEditing,
})
return (
<div>
{isEditing ? (
<input autoFocus onBlur={() => setIsEditing(false)} />
) : (
<p>Press 'e' to edit</p>
)}
</div>
)
}
State-Based Enabling
import { useHotkeys } from 'react-hotkeys-hook'
import { useState } from 'react'
function Document() {
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false)
const [isOnline, setIsOnline] = useState(true)
// Only enable save when there are changes AND online
useHotkeys('ctrl+s', handleSave, {
enabled: hasUnsavedChanges && isOnline,
preventDefault: true,
})
return <div>Content</div>
}
Dynamic Enable/Disable with Functions
For more complex logic, use a function that returns a boolean:
import { useHotkeys } from 'react-hotkeys-hook'
function AdvancedEditor() {
useHotkeys('ctrl+b', handleBold, {
enabled: (keyboardEvent, hotkeysEvent) => {
// Check if we're in a text input
const target = keyboardEvent.target as HTMLElement
const isInput = target.tagName === 'INPUT' || target.tagName === 'TEXTAREA'
// Only enable if in an input AND user has permission
return isInput && hasEditPermission()
},
})
}
Runtime Validation
import { useHotkeys } from 'react-hotkeys-hook'
function ConditionalHotkeys() {
useHotkeys('ctrl+delete', handleDelete, {
enabled: (keyboardEvent) => {
// Don't allow delete if readonly mode
if (isReadOnly) return false
// Don't allow delete if nothing is selected
if (!hasSelection()) return false
// Require confirmation for destructive action
return window.confirm('Delete selected items?')
},
preventDefault: true,
})
}
Based on User Permissions
import { useHotkeys } from 'react-hotkeys-hook'
import { useAuth } from './auth'
function AdminPanel() {
const { user } = useAuth()
// Admin-only hotkey
useHotkeys('ctrl+shift+a', openAdminPanel, {
enabled: user?.role === 'admin',
})
// Pro user features
useHotkeys('ctrl+shift+p', openProFeatures, {
enabled: user?.plan === 'pro',
})
}
Feature Flags
import { useHotkeys } from 'react-hotkeys-hook'
import { useFeatureFlag } from './features'
function BetaFeatures() {
const aiAssistEnabled = useFeatureFlag('ai-assist')
useHotkeys('ctrl+space', openAIAssist, {
enabled: aiAssistEnabled,
description: 'Open AI assistant',
})
}
Loading States
import { useHotkeys } from 'react-hotkeys-hook'
import { useState } from 'react'
function DataTable() {
const [isLoading, setIsLoading] = useState(false)
// Disable navigation while loading
useHotkeys('j', moveDown, { enabled: !isLoading })
useHotkeys('k', moveUp, { enabled: !isLoading })
useHotkeys('r', refresh, { enabled: !isLoading })
return <div>Table content</div>
}
Modal/Dialog States
import { useHotkeys } from 'react-hotkeys-hook'
import { useState } from 'react'
function App() {
const [isModalOpen, setIsModalOpen] = useState(false)
// Disable global shortcuts when modal is open
useHotkeys('ctrl+k', openCommandPalette, {
enabled: !isModalOpen,
})
// Modal-specific shortcuts
useHotkeys('escape', () => setIsModalOpen(false), {
enabled: isModalOpen,
})
return (
<div>
<button onClick={() => setIsModalOpen(true)}>Open Modal</button>
{isModalOpen && <Modal />}
</div>
)
}
With Dependencies
When using state in the enabled function, include it in dependencies:
import { useHotkeys } from 'react-hotkeys-hook'
import { useState } from 'react'
function Editor() {
const [mode, setMode] = useState<'view' | 'edit'>('view')
const [hasChanges, setHasChanges] = useState(false)
useHotkeys(
'ctrl+s',
handleSave,
{
enabled: mode === 'edit' && hasChanges,
preventDefault: true,
},
[mode, hasChanges] // Include state in dependencies
)
}
Temporarily Disable All Hotkeys
import { useHotkeys } from 'react-hotkeys-hook'
import { useState } from 'react'
function useGlobalHotkeyToggle() {
const [hotkeysEnabled, setHotkeysEnabled] = useState(true)
return { hotkeysEnabled, setHotkeysEnabled }
}
function App() {
const { hotkeysEnabled, setHotkeysEnabled } = useGlobalHotkeyToggle()
// All hotkeys respect the global toggle
useHotkeys('ctrl+s', handleSave, { enabled: hotkeysEnabled })
useHotkeys('ctrl+k', handleCommand, { enabled: hotkeysEnabled })
useHotkeys('ctrl+p', handlePrint, { enabled: hotkeysEnabled })
return (
<div>
<label>
<input
type="checkbox"
checked={hotkeysEnabled}
onChange={(e) => setHotkeysEnabled(e.target.checked)}
/>
Enable keyboard shortcuts
</label>
</div>
)
}
When disabling hotkeys based on state, the hook still listens to keyboard events. For better performance with many hotkeys, consider using scopes instead:
import { useHotkeys, HotkeysProvider, useHotkeysContext } from 'react-hotkeys-hook'
function App() {
return (
<HotkeysProvider initiallyActiveScopes={['view']}>
<Editor />
</HotkeysProvider>
)
}
function Editor() {
const { enableScope, disableScope } = useHotkeysContext()
// Instead of enabled: isViewMode
useHotkeys('j', moveDown, { scopes: 'view' })
useHotkeys('k', moveUp, { scopes: 'view' })
// Instead of enabled: isEditMode
useHotkeys('ctrl+b', makeBold, { scopes: 'edit' })
useHotkeys('ctrl+i', makeItalic, { scopes: 'edit' })
const switchToEditMode = () => {
disableScope('view')
enableScope('edit')
}
}
When enabled is false, the hook still listens to keyboard events but doesn’t trigger the callback. This is different from scopes, where inactive scopes don’t process events at all.
For better performance with many hotkeys that toggle together, use scopes instead of the enabled option.