Lesson 4 of 6
Forms and state
Let native controls send values, and decide who remembers a component’s current state.
Name values that a form should send
A form only sends a control when it has a name. Put name on native inputs, checkboxes, and form-enabled picker roots. For example, Select uses its name to create a visually hidden native select proxy for submission.
<form>
<Input name="email" type="email" />
<Select name="size" defaultValue="small">
<Label>Size</Label>
<SelectTrigger><SelectValue /></SelectTrigger>
<SelectPopover>...</SelectPopover>
</Select>
</form>Add a value by pressing Enter
An input beside a submit button is just a form. A text input and a Button with type="submit" share one form, so pressing Enter in the field and pressing the button both fire the form's onSubmit — you never write a key handler for it. Give the Input a name, read that value from the submit event, then reset the form for the next entry. This is the whole “add item” field, composed from pieces you already have.
<form
onSubmit={(event) => {
event.preventDefault();
const form = event.currentTarget;
onAdd(String(new FormData(form).get("item")));
form.reset();
}}
>
<TextField>
<Label>New item</Label>
<Input name="item" placeholder="Add an item" />
</TextField>
<Button type="submit">Add</Button>
</form>Control state when your app needs to know now
Use value with onChange when your app owns a selected value. Use open with onToggle when your app owns whether an overlay is open. The component asks for a change, and your state gives it the new value back.
const [open, setOpen] = useState(false);
<Dialog open={open} onToggle={setOpen}>...</Dialog>Use a default for a starting value
Use defaultValue, defaultSelected, or defaultOpen when the component may remember its own state after the first render. This is simpler for a small form that does not need live app state. Do not pass both a controlled value and expect a default to keep changing it later.
<Checkbox defaultSelected>Send me updates</Checkbox>
<Accordion defaultValue="shipping">...</Accordion>