Utility Hooks
Timer, animation, and helper hooks for common Stream Deck patterns.
useInterval
Safe interval hook that auto-cleans on unmount. Pass null to pause.
function useInterval(callback: () => void, delayMs: number | null): IntervalControls;interface IntervalControls {
reset: () => void;
}function ClockKey() {
const [time, setTime] = useState(new Date());
useInterval(() => {
setTime(new Date());
}, 1000);
return (
<div
style={{
width: "100%",
height: "100%",
alignItems: "center",
justifyContent: "center",
background: "#000",
}}
>
<span style={{ color: "white", fontSize: 22 }}>{time.toLocaleTimeString()}</span>
</div>
);
}Call reset() on the returned controls to restart the interval from zero.
useTimeout
Safe timeout hook that auto-cleans on unmount. Pass null to cancel.
function useTimeout(callback: () => void, delayMs: number | null): TimeoutControls;interface TimeoutControls {
cancel: () => void;
reset: () => void;
}usePrevious
Returns the previous value of a variable from the last render.
function usePrevious<T>(value: T): T | undefined;function MyKey() {
const [count, setCount] = useState(0);
const prev = usePrevious(count);
// prev is undefined on first render, then trails count by one render
}useTick
Calls the callback repeatedly with delta time using timer-driven ticks. Pass a number to set target FPS, true for 30fps, or false to pause.
function useTick(callback: (deltaMs: number) => void, fpsOrActive?: number | boolean): void;Default FPS is 30. Maximum FPS is capped at 30 — Stream Deck hardware does not display updates faster than 30Hz, so higher tick rates would only create extra React/state churn with no visible benefit. The callback receives the elapsed milliseconds since the last tick.
function AnimatedKey() {
const [rotation, setRotation] = useState(0);
useTick((delta) => {
setRotation((r) => (r + delta * 0.1) % 360);
});
// ...
}