@fcannizzaro/streamdeck-react

Context Hooks

Access device info, action metadata, canvas dimensions, and the raw SDK from React components.

useDevice

Returns information about the Stream Deck device this action instance is running on.

function useDevice(): DeviceInfo;
interface DeviceInfo {
  id: string;
  /** Numeric device type matching Elgato DeviceType enum values (e.g. 7 = StreamDeckPlus). */
  type: number;
  size: { columns: number; rows: number };
  name: string;
}

The value is set once on mount and does not change.

useAction

Returns metadata about the current action instance.

function useAction(): ActionInfo;
interface ActionInfo {
  id: string; // Unique context ID for this placed instance
  uuid: string; // Action UUID (e.g. 'com.example.plugin.counter')
  controller: "Keypad" | "Encoder";
  coordinates?: { row: number; column: number };
  isInMultiAction: boolean;
}

Use isInMultiAction to adapt rendering for multi-action contexts:

function SmartKey() {
  const { isInMultiAction } = useAction();

  if (isInMultiAction) {
    return <SimpleIcon />;
  }
  return <FullDashboard />;
}

useCanvas

Returns the rendering dimensions for the current key, dial, or touch surface.

function useCanvas(): CanvasInfo;
interface CanvasInfo {
  width: number; // Pixel width of the render target
  height: number; // Pixel height of the render target
  type: "key" | "dial" | "touch";
}

The root wrapper div is automatically sized to these dimensions. Your component renders within it:

function MyKey() {
  const { width, height } = useCanvas();

  return <div style={{ width, height, background: "#000" }}>{/* ... */}</div>;
}

See Device Sizes for the full dimension table.

useStreamDeck

Provides access to the adapter and the action handle for the current action root. The adapter routes all SDK operations, and the action handle provides per-action methods like setImage, setFeedback, showAlert, etc.

function useStreamDeck(): StreamDeckAccess;
interface StreamDeckAccess {
  action: AdapterActionHandle;
  adapter: StreamDeckAdapter;
}

Use this for operations not yet wrapped by the library's built-in hooks:

function AdvancedKey() {
  const { action, adapter } = useStreamDeck();

  useKeyDown(async () => {
    await action.showOk();
    await adapter.openUrl("https://example.com");
  });

  return <div style={{ width: "100%", height: "100%", background: "#000" }} />;
}

The action is an AdapterActionHandle -- a flat interface that unifies Key/Dial/Action. Methods not applicable for the current surface (e.g., setImage on a dial) resolve as no-ops. See Adapter for details.

Prefer the dedicated hooks (useOpenUrl, useShowAlert, etc.) when available.

useSize

Returns a size helper bound to the current canvas dimensions. Provides percentage-based and proportional size calculations for building responsive layouts across different Stream Deck surfaces.

function useSize(): SizeHelper;
interface SizeHelper {
  readonly width: number;
  readonly height: number;
  readonly min: number;
  readonly max: number;
  readonly square: boolean;
  readonly landscape: boolean;
  readonly portrait: boolean;
  readonly aspectRatio: number;
  w(percent: number): number;
  h(percent: number): number;
  minP(percent: number): number;
  maxP(percent: number): number;
  scale(basePx: number, referenceSize?: number): number;
}

The helper is memoized on canvas dimensions — since CanvasInfo is stable for the lifetime of a root, the helper is created once per mount.

function AdaptiveKey() {
  const size = useSize();

  return (
    <div className="flex flex-col items-center justify-center w-full h-full bg-[#1a1a1a]">
      <span style={{ fontSize: size.scale(24), color: "white" }}>
        {size.square ? "KEY" : "DIAL"}
      </span>
    </div>
  );
}

See Size Utility for the full guide with all methods and common patterns.

On this page