@fcannizzaro/streamdeck-react

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);
  });

  // ...
}

On this page