Skip to content

Latest commit

 

History

History
75 lines (55 loc) · 2.35 KB

guide-controlled-uncontrolled.md

File metadata and controls

75 lines (55 loc) · 2.35 KB

Controlled vs Uncontrolled State Guide

Overview

All stateful components in @bitcode/ui follow the ADR-007 controlled/uncontrolled pattern. You can use components in two modes:

  1. Controlled — you manage the state externally
  2. Uncontrolled — the component manages its own state

Pattern

Every stateful prop has three pieces:

Prop Purpose
value / open / checked Controlled — you own the state
defaultValue / defaultOpen / defaultChecked Uncontrolled — initial value only
onValueChange / onOpenChange / onCheckedChange Callback — fires on every change

Examples

Uncontrolled (simplest)

// Component manages its own state. You just read changes.
<BcInput
  name="email"
  defaultValue="john@example.com"
  onValueChange={(value, meta) => console.log(value)}
/>

Controlled (full control)

const [email, setEmail] = useState('');

<BcInput
  name="email"
  value={email}
  onValueChange={(value, meta) => setEmail(value)}
/>

Migration from legacy API

If you're using the old initialX props, migrate to defaultX:

// ❌ Old (deprecated)
<BcDataTable initialSort={[{ field: 'name', direction: 'asc' }]} />

// ✅ New
<BcDataTable defaultSortModel={[{ field: 'name', direction: 'asc' }]} />

Full reference

State Controlled Uncontrolled Callback
value value defaultValue onValueChange
open open defaultOpen onOpenChange
checked checked defaultChecked onCheckedChange
selected keys selectedKeys defaultSelectedKeys onSelectionChange
active key activeKey defaultActiveKey onActiveKeyChange
expanded keys expandedKeys defaultExpandedKeys onExpandedChange
sort model sortModel defaultSortModel onSortModelChange
filter model filterModel defaultFilterModel onFilterModelChange
column state columnState defaultColumnState onColumnStateChange

Rules

  1. Never mutate a controlled prop internally. The component treats value/open/checked as read-only.
  2. initialX is deprecated. Use defaultX instead. Legacy aliases exist for backward compatibility.
  3. Callback meta always includes reason + source. This lets you distinguish user input from programmatic changes.