<option>

Declares one choice inside a dropdown, carrying the value submitted with the form.

Signature
<select>
  <option value="someOption">Some option</option>
  <option value="otherOption">Other option</option>
</select>

Parameters

ParameterTypeDescription
$valueoptionalstringThe value to be used when submitting the parent <select> in a form if this option is selected. It is also the string the parent's value or defaultValue is matched against.
$childrenoptionalReactNodeThe text shown for this choice. Used as the option's label when no label prop is given.
$labeloptionalstringSpecifies the meaning of the option. If not specified, the text inside the option is used.
$disabledoptionalboolean= falseIf true, the option will not be selectable and will appear dimmed.
$...propsoptionalHTMLOptionElement props<option> supports all common element props, including ref, className and style. It does not support selected.

Return value

ReactElementRenders a browser <option> element inside a <select>, <optgroup> or <datalist>.

Errors

React does not support the selected attribute on <option> and logs an error when it is passed; set the parent <select value> or <select defaultValue> instead.

An <option> is a leaf: it declares a choice and the string that choice submits. It never decides whether it is selected — that belongs to the parent <select> through value or defaultValue. The selected attribute you would write in HTML is unsupported in React and produces an error, which is the single most common surprise on this element.

Practical rules

  • Give every option an explicit value. Without one the browser falls back to the option's text, so renaming a label silently changes what the form submits.
  • Values are strings. An option built from a numeric id needs value={String(id)}, or the comparison against the select's value quietly fails and the box renders blank.
  • When mapping over data, key and value are different props with different jobs — key is for React's reconciler and never reaches the DOM.
  • label overrides the child text in the popup on some browsers; leave it off unless you deliberately want two different strings.
  • A placeholder is an ordinary option with value="", usually marked disabled so the user cannot return to it, and paired with required on the select.

Example

Try it yourself
Loading editor…
Loading React…

When to use it

  • Render a dropdown's choices by mapping over an array of records
  • Add a disabled 'Choose one' placeholder so a required select starts empty
  • Group and dim options that are unavailable, such as sold-out sizes

Frequently asked questions

How do I mark an option as selected in React?

You do not set it on the option. Pass that option's value string to the parent select — <select defaultValue="m"> for an uncontrolled dropdown or <select value={size}> for a controlled one. React explicitly does not support the selected attribute on <option> and errors when it sees one.

Do I need a value on every option?

Practically, yes. An option without a value submits its own text content, so any change to the visible label changes the submitted data. It also has to match the parent select's value exactly for the right option to appear selected, and matching against display text is fragile.

How do I add a placeholder to a select?

Render a first <option value="" disabled> with your placeholder text and start the select's value at the empty string. Adding required to the select then blocks submission until a real choice is made, and disabled stops the user from returning to the placeholder.

More examples

Options from data, with numeric ids

The dropdown opens on Grace Hopper and the paragraph reads `Assigned to Grace Hopper (id 12)`. State holds a real number, but the DOM only speaks strings, so the value prop is stringified on the way in and the change handler parses on the way out. Skipping either conversion is the usual cause of a select that renders blank or a lookup that returns undefined, because 12 and "12" never match with ===.

Example · jsx
import { useState } from "react";

const USERS = [
  { id: 7, name: "Ada Lovelace" },
  { id: 12, name: "Grace Hopper" },
  { id: 19, name: "Alan Turing" },
];

export default function AssigneePicker() {
  const [assigneeId, setAssigneeId] = useState(12);
  const assignee = USERS.find((user) => user.id === assigneeId);

  return (
    <div>
      <select
        value={String(assigneeId)}
        onChange={(e) => setAssigneeId(Number(e.target.value))}
      >
        {USERS.map((user) => (
          <option key={user.id} value={String(user.id)}>
            {user.name}
          </option>
        ))}
      </select>
      <p>Assigned to {assignee.name} (id {assigneeId})</p>
    </div>
  );
}

label and children are not the same thing

The dropdown opens on the middle option because the parent's defaultValue is "m". That option carries both children ("Medium") and a label prop; browsers that honour label show "Medium (recommended)" in the popup while the children remain the fallback, so the two strings can disagree. The third option is dimmed and unselectable but still present in the markup, which is how you show an unavailable choice rather than hiding it.

Example · jsx
export default function SizeLegend() {
  return (
    <select defaultValue="m">
      <option value="s">Small</option>
      <option value="m" label="Medium (recommended)">
        Medium
      </option>
      <option value="l" disabled>
        Large — out of stock
      </option>
    </select>
  );
}

Discussion

  • Be the first to comment on this lesson.