Event Hooks
React hooks for Stream Deck hardware events -- key presses, dial rotation, touch taps, and dial hints.
Event hooks subscribe to Stream Deck hardware events and fire callbacks inside the React tree.
useKeyDown
Fires when a key is pressed down.
function useKeyDown(callback: (payload: KeyDownPayload) => void): void;interface KeyDownPayload {
settings: JsonObject;
isInMultiAction: boolean;
state?: number;
userDesiredState?: number;
}function CounterKey() {
const [count, setCount] = useState(0);
useKeyDown(() => {
setCount((c) => c + 1);
});
return (
<div style={{ width: '100%', height: '100%', alignItems: 'center', justifyContent: 'center', background: '#000' }}>
<span style={{ color: 'white', fontSize: 32 }}>{count}</span>
</div>
);
}useKeyUp
Fires when a key is released.
function useKeyUp(callback: (payload: KeyUpPayload) => void): void;interface KeyUpPayload {
settings: JsonObject;
isInMultiAction: boolean;
state?: number;
userDesiredState?: number;
}function HoldKey() {
const [pressed, setPressed] = useState(false);
useKeyDown(() => setPressed(true));
useKeyUp(() => setPressed(false));
return (
<div style={{
width: '100%', height: '100%',
alignItems: 'center', justifyContent: 'center',
background: pressed ? '#4CAF50' : '#333',
}}>
<span style={{ color: 'white', fontSize: 18 }}>
{pressed ? 'HELD' : 'PRESS'}
</span>
</div>
);
}useDialRotate
Fires when a dial/encoder is rotated.
function useDialRotate(callback: (payload: DialRotatePayload) => void): void;interface DialRotatePayload {
ticks: number; // Positive = clockwise, negative = counter-clockwise
pressed: boolean; // Whether the dial is pressed while rotating
settings: JsonObject;
}function VolumeDial() {
const [volume, setVolume] = useState(50);
useDialRotate(({ ticks }) => {
setVolume((v) => Math.max(0, Math.min(100, v + ticks)));
});
return (
<div style={{ width: '100%', height: '100%', alignItems: 'center', justifyContent: 'center', background: '#1a1a1a' }}>
<span style={{ color: 'white', fontSize: 28 }}>{volume}%</span>
</div>
);
}useDialDown / useDialUp
Fire when a dial is pressed / released.
function useDialDown(callback: (payload: DialPressPayload) => void): void;
function useDialUp(callback: (payload: DialPressPayload) => void): void;interface DialPressPayload {
settings: JsonObject;
controller: 'Encoder';
}useTouchTap
Fires when the touch strip area is tapped.
function useTouchTap(callback: (payload: TouchTapPayload) => void): void;interface TouchTapPayload {
tapPos: [x: number, y: number]; // Coordinates of the tap
hold: boolean; // Whether it was a long press
settings: JsonObject;
}useDialHint
Sets the trigger descriptions shown on Stream Deck+ for what the dial actions do. Updates automatically when hints change.
function useDialHint(hints: DialHints): void;interface DialHints {
rotate?: string;
press?: string;
touch?: string;
longTouch?: string;
}function VolumeDial() {
const [muted, setMuted] = useState(false);
useDialHint({
rotate: 'Adjust volume',
press: muted ? 'Unmute' : 'Mute',
});
// ...
}Under the hood, useDialHint calls action.setTriggerDescription() whenever the hint values change.
Implementation Pattern
All event hooks follow the same internal pattern: they subscribe to the root's EventBus via useEffect and use a stable callback ref to avoid stale closures without causing re-subscriptions.