Settings Hooks
Bi-directional settings sync between React state and the Stream Deck SDK.
useSettings
Returns a [settings, setSettings] tuple with shallow-merge semantics. Changes are synced bidirectionally between the React tree and the Stream Deck SDK.
function useSettings<S extends JsonObject = JsonObject>(): [S, (partial: Partial<S>) => void];Merge Semantics
setSettings does a shallow merge ({ ...current, ...partial }), matching the Stream Deck SDK's setSettings behavior. This is intentionally different from React's useState -- it always merges, never replaces.
Example
type MySettings = { color: string; brightness: number };
function MyKey() {
const [settings, setSettings] = useSettings<MySettings>();
useKeyDown(() => {
setSettings({ brightness: Math.min(100, settings.brightness + 10) });
});
return (
<div style={{
width: '100%', height: '100%',
background: settings.color,
opacity: settings.brightness / 100,
alignItems: 'center', justifyContent: 'center',
}}>
<span style={{ color: 'white', fontSize: 20 }}>{settings.brightness}%</span>
</div>
);
}Sync Flow
- React to SDK: calling
setSettings({ count: 5 })updates the internal React state (triggers re-render) and callsaction.setSettings()on the SDK to persist. - SDK to React: when the Property Inspector saves settings (triggering
onDidReceiveSettings), the internal state updates and components usinguseSettings()re-render. - Conflict resolution: the SDK is the source of truth. Last write wins.
useGlobalSettings
Same pattern as useSettings, but for plugin-wide global settings shared across all action instances.
function useGlobalSettings<G extends JsonObject = JsonObject>(): [G, (partial: Partial<G>) => void];type GlobalConfig = { apiKey: string; theme: 'light' | 'dark' };
function MyKey() {
const [global] = useGlobalSettings<GlobalConfig>();
return (
<div style={{
width: '100%', height: '100%',
background: global.theme === 'dark' ? '#000' : '#fff',
alignItems: 'center', justifyContent: 'center',
}}>
<span style={{ color: global.theme === 'dark' ? '#fff' : '#000', fontSize: 14 }}>
{global.apiKey ? 'Connected' : 'No API Key'}
</span>
</div>
);
}See also Settings & Property Inspector for the full sync architecture.