Quick Start
This guide will help you get up and running with react-hotkeys-hook quickly. We’ll cover the most common use cases with real examples.
Basic Usage
The simplest way to use the hook is to pass a key combination and a callback function:
import { useHotkeys } from 'react-hotkeys-hook'
import { useState } from 'react'
export const Counter = () => {
const [ count , setCount ] = useState ( 0 )
useHotkeys ( 'ctrl+k' , () => setCount ( count + 1 ), [ count ])
return (
< p >
Pressed { count } times.
</ p >
)
}
Notice the dependency array [count] at the end - just like useCallback, you need to include any variables from your component that the callback uses.
Key Combinations
Single Keys
Listen to individual keys:
useHotkeys ( 'a' , () => console . log ( 'Pressed A' ))
useHotkeys ( 'esc' , () => console . log ( 'Pressed Escape' ))
useHotkeys ( 'space' , () => console . log ( 'Pressed Space' ))
Modifier Keys
Combine keys with modifiers like ctrl, shift, alt, and meta:
useHotkeys ( 'ctrl+s' , () => console . log ( 'Save' ))
useHotkeys ( 'meta+shift+a' , () => console . log ( 'Select all (Mac)' ))
useHotkeys ( 'alt+b' , () => console . log ( 'Bold' ))
Use mod instead of meta or ctrl to automatically use Cmd on Mac and Ctrl on Windows/Linux: useHotkeys ( 'mod+s' , () => console . log ( 'Save' )) // Cmd+S on Mac, Ctrl+S elsewhere
Multiple Hotkeys
Listen to multiple key combinations with the same callback:
// Using an array
useHotkeys ([ 'ctrl+k' , 'ctrl+p' ], () => console . log ( 'Command palette' ))
// Or using a comma-separated string
useHotkeys ( 'ctrl+k, ctrl+p' , () => console . log ( 'Command palette' ))
Key Sequences
Create Vim-style key sequences:
useHotkeys ( 'y>e>e>t' , () => console . log ( 'Yeet!' ))
Sequences use > by default to separate keys. You have 1000ms between keypresses before the sequence resets.
Working with Options
The hook accepts an options object to customize behavior:
Prevent Default Behavior
Prevent the browser’s default action for a key combination:
useHotkeys ( 'meta+s' , () => {
console . log ( 'Saving...' )
// Your save logic here
}, { preventDefault: true })
By default, hotkeys are disabled when typing in input fields. Enable them if needed:
// Enable on all form fields
useHotkeys ( 'ctrl+enter' , () => console . log ( 'Submit' ), { enableOnFormTags: true })
// Enable only on specific form tags
useHotkeys ( 'ctrl+enter' , () => console . log ( 'Submit' ), {
enableOnFormTags: [ 'textarea' ]
})
Key Up vs Key Down
// Trigger on key release instead of key press
useHotkeys ( 'shift' , () => console . log ( 'Shift released' ), { keyup: true })
// Trigger on both key down and key up
useHotkeys ( 'a' , () => console . log ( 'Key event' ), {
keyup: true ,
keydown: true
})
Conditional Enabling
Enable or disable hotkeys based on state:
const [ isEnabled , setIsEnabled ] = useState ( true )
useHotkeys ( 'ctrl+k' , () => console . log ( 'Triggered' ), {
enabled: isEnabled
})
Focus Trapping
Limit hotkeys to a specific element by using the returned ref:
import { useHotkeys } from 'react-hotkeys-hook'
import { useState } from 'react'
export const FocusedCounter = () => {
const [ count , setCount ] = useState ( 0 )
const ref = useHotkeys < HTMLDivElement >(
'ctrl+k' ,
() => setCount ( prevCount => prevCount + 1 )
)
return (
< div ref = { ref } tabIndex = { - 1 } style = { { padding: '20px' , border: '2px solid blue' } } >
Click here and press Ctrl+K. Count: { count }
</ div >
)
}
The element must be focusable for this to work. Add tabIndex={-1} or tabIndex={0} to make an element focusable.
Using Scopes
Scopes let you organize hotkeys and enable/disable groups of shortcuts:
import { HotkeysProvider , useHotkeys , useHotkeysContext } from 'react-hotkeys-hook'
import { useState } from 'react'
function App () {
return (
< HotkeysProvider initiallyActiveScopes = { [ 'settings' ] } >
< SettingsPanel />
</ HotkeysProvider >
)
}
function SettingsPanel () {
const [ count , setCount ] = useState ( 0 )
const { toggleScope } = useHotkeysContext ()
// This hotkey only works when 'settings' scope is active
useHotkeys ( 'ctrl+k' , () => setCount ( prevCount => prevCount + 1 ), {
scopes: [ 'settings' ]
})
return (
< div >
< p > Pressed { count } times </ p >
< button onClick = { () => toggleScope ( 'settings' ) } >
Toggle Settings Scope
</ button >
</ div >
)
}
Checking Pressed Keys
Check if a key is currently being held down:
import { isHotkeyPressed } from 'react-hotkeys-hook'
function MyComponent () {
const handleClick = () => {
if ( isHotkeyPressed ( 'shift' )) {
console . log ( 'Shift-clicking!' )
} else {
console . log ( 'Normal click' )
}
}
return < button onClick = { handleClick } > Click me </ button >
}
Common Patterns
Command Palette
import { useHotkeys } from 'react-hotkeys-hook'
import { useState } from 'react'
export const CommandPalette = () => {
const [ isOpen , setIsOpen ] = useState ( false )
useHotkeys ( 'mod+k' , () => setIsOpen ( true ), { preventDefault: true })
useHotkeys ( 'esc' , () => setIsOpen ( false ), { enabled: isOpen })
if ( ! isOpen ) return null
return (
< div className = "command-palette" >
< input placeholder = "Type a command..." autoFocus />
</ div >
)
}
Keyboard Navigation
import { useHotkeys } from 'react-hotkeys-hook'
import { useState } from 'react'
export const List = ({ items }) => {
const [ selectedIndex , setSelectedIndex ] = useState ( 0 )
useHotkeys ( 'up' , () => setSelectedIndex ( i => Math . max ( 0 , i - 1 )))
useHotkeys ( 'down' , () => setSelectedIndex ( i => Math . min ( items . length - 1 , i + 1 )))
useHotkeys ( 'enter' , () => console . log ( 'Selected:' , items [ selectedIndex ]))
return (
< ul >
{ items . map (( item , index ) => (
< li
key = { index }
style = { {
background: index === selectedIndex ? 'lightblue' : 'white'
} }
>
{ item }
</ li >
)) }
</ ul >
)
}
import { useHotkeys } from 'react-hotkeys-hook'
export const Form = () => {
const handleSubmit = () => {
console . log ( 'Form submitted' )
}
useHotkeys ( 'ctrl+enter' , handleSubmit , {
enableOnFormTags: [ 'textarea' , 'input' ]
})
return (
< form onSubmit = { ( e ) => { e . preventDefault (); handleSubmit (); } } >
< textarea placeholder = "Press Ctrl+Enter to submit" />
< button type = "submit" > Submit </ button >
</ form >
)
}
Next Steps
Now that you understand the basics, explore the full API documentation to learn about all available options and advanced features:
API Reference Complete API documentation for all hooks and utilities
Core Concepts Learn about scopes, sequences, and focus trapping