内置浏览器<select>组件允许您渲染带有选项的选择框。

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

参考

<select>

要显示选择框,请渲染内置浏览器<select>组件。

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

请参见下面的更多示例。

属性

<select>支持所有通用的元素属性。

您可以使选择框受控,方法是传递value属性

  • value:字符串(对于multiple={true},则为字符串数组)。控制选择哪个选项。每个值字符串都与<select>内部某些<option>value匹配。

传递value时,还必须传递一个更新传递值的onChange处理程序。

如果您的<select>不受控,则可以改用defaultValue属性

这些<select>属性与不受控和受控选择框都相关

  • autoComplete:字符串。指定可能的自动完成行为之一。
  • autoFocus:布尔值。如果为true,React将在挂载时聚焦该元素。
  • children: <select> 接受以下组件作为子组件:<option><optgroup><datalist>。只要最终渲染出上述允许的组件之一,你也可以传递你自己的组件。如果你传递最终渲染<option>标签的自定义组件,那么你渲染的每个<option>都必须具有一个value属性。
  • disabled: 布尔值。如果为true,则选择框将不可交互,并且将显示为灰暗状态。
  • form: 字符串。指定此选择框所属的<form>元素的id。如果省略,则为最近的父级表单。
  • multiple: 布尔值。如果为true,则浏览器允许多选
  • name: 字符串。指定此选择框的名称,该名称将与表单一起提交
  • onChange: 一个Event 处理程序 函数。对于受控选择框是必需的。当用户选择不同的选项时立即触发。行为类似于浏览器的input 事件
  • onChangeCapture: onChange 的一个版本,它在捕获阶段触发。
  • onInput: 一个Event 处理程序 函数。当用户更改值时立即触发。出于历史原因,在 React 中习惯上使用onChange,其作用类似。
  • onInputCapture: onInput 的一个版本,它在捕获阶段触发。
  • onInvalid: 一个Event 处理程序 函数。如果表单提交时输入验证失败,则触发。与内置的invalid事件不同,React 的onInvalid 事件会冒泡。
  • onInvalidCapture: onInvalid 的一个版本,它在捕获阶段触发。
  • required: 布尔值。如果为true,则必须提供值才能提交表单。
  • size: 数字。对于multiple={true} 选择,指定初始可见项目的首选数量。

注意事项

  • 与HTML不同,不支持向selected 属性传递给 <option>。 请改用 <select defaultValue> 用于非受控选择框和 <select value> 用于受控选择框。
  • 如果选择框接收 value 属性,则它将被 视为受控的。
  • 选择框不能同时受控和不受控。
  • 选择框在其生命周期内不能在受控和不受控之间切换。
  • 每个受控选择框都需要一个 onChange 事件处理程序,该处理程序同步更新其后备值。

用法

显示带有选项的选择框

渲染一个包含 <option> 组件列表的 <select> 来显示选择框。 为每个 <option> 提供一个 value,表示要与表单一起提交的数据。

export default function FruitPicker() {
  return (
    <label>
      Pick a fruit:
      <select name="selectedFruit">
        <option value="apple">Apple</option>
        <option value="banana">Banana</option>
        <option value="orange">Orange</option>
      </select>
    </label>
  );
}


为选择框提供标签

通常,您会将每个 <select> 放入 <label> 标签中。 这会告诉浏览器此标签与该选择框相关联。 当用户点击标签时,浏览器会自动聚焦选择框。 这对于辅助功能也很重要:当用户聚焦选择框时,屏幕阅读器会宣布标签标题。

如果无法将 <select> 嵌套到 <label> 中,请通过向 <select id><label htmlFor> 传递相同的 ID 来关联它们。 为避免一个组件的多个实例之间发生冲突,请使用 useId 生成此类 ID。

import { useId } from 'react';

export default function Form() {
  const vegetableSelectId = useId();
  return (
    <>
      <label>
        Pick a fruit:
        <select name="selectedFruit">
          <option value="apple">Apple</option>
          <option value="banana">Banana</option>
          <option value="orange">Orange</option>
        </select>
      </label>
      <hr />
      <label htmlFor={vegetableSelectId}>
        Pick a vegetable:
      </label>
      <select id={vegetableSelectId} name="selectedVegetable">
        <option value="cucumber">Cucumber</option>
        <option value="corn">Corn</option>
        <option value="tomato">Tomato</option>
      </select>
    </>
  );
}


提供初始选定的选项

默认情况下,浏览器将选择列表中的第一个 <option>。 要默认选择其他选项,请将该 <option>value 作为 defaultValue 传递给 <select> 元素。

export default function FruitPicker() {
  return (
    <label>
      Pick a fruit:
      <select name="selectedFruit" defaultValue="orange">
        <option value="apple">Apple</option>
        <option value="banana">Banana</option>
        <option value="orange">Orange</option>
      </select>
    </label>
  );
}

陷阱

与HTML不同,不支持向单个 <option> 传递 selected 属性。


启用多选

<select> 传递 multiple={true} 以允许用户选择多个选项。 在这种情况下,如果您还指定 defaultValue 来选择初始选定的选项,则它必须是一个数组。

export default function FruitPicker() {
  return (
    <label>
      Pick some fruits:
      <select
        name="selectedFruit"
        defaultValue={['orange', 'banana']}
        multiple={true}
      >
        <option value="apple">Apple</option>
        <option value="banana">Banana</option>
        <option value="orange">Orange</option>
      </select>
    </label>
  );
}


提交表单时读取选择框的值

在选择框周围添加一个 <form>,并在其中包含一个 <button type="submit">。 它将调用您的 <form onSubmit> 事件处理程序。 默认情况下,浏览器会将表单数据发送到当前 URL 并刷新页面。 您可以通过调用 e.preventDefault() 来覆盖此行为。 使用 new FormData(e.target) 读取表单数据。

export default function EditPost() {
  function handleSubmit(e) {
    // Prevent the browser from reloading the page
    e.preventDefault();
    // Read the form data
    const form = e.target;
    const formData = new FormData(form);
    // You can pass formData as a fetch body directly:
    fetch('/some-api', { method: form.method, body: formData });
    // You can generate a URL out of it, as the browser does by default:
    console.log(new URLSearchParams(formData).toString());
    // You can work with it as a plain object.
    const formJson = Object.fromEntries(formData.entries());
    console.log(formJson); // (!) This doesn't include multiple select values
    // Or you can get an array of name-value pairs.
    console.log([...formData.entries()]);
  }

  return (
    <form method="post" onSubmit={handleSubmit}>
      <label>
        Pick your favorite fruit:
        <select name="selectedFruit" defaultValue="orange">
          <option value="apple">Apple</option>
          <option value="banana">Banana</option>
          <option value="orange">Orange</option>
        </select>
      </label>
      <label>
        Pick all your favorite vegetables:
        <select
          name="selectedVegetables"
          multiple={true}
          defaultValue={['corn', 'tomato']}
        >
          <option value="cucumber">Cucumber</option>
          <option value="corn">Corn</option>
          <option value="tomato">Tomato</option>
        </select>
      </label>
      <hr />
      <button type="reset">Reset</button>
      <button type="submit">Submit</button>
    </form>
  );
}

注意

为你的 <select> 元素指定一个 name 属性,例如 <select name="selectedFruit" />。你指定的 name 属性值将作为表单数据中的键,例如 { selectedFruit: "orange" }

如果你使用 <select multiple={true}>,你从表单中读取的 FormData 对象将包含每个被选中的值作为一个单独的键值对。请仔细查看上面示例中的控制台日志。

陷阱

默认情况下,<form> 表单内的任何 <button> 元素都会提交表单。这可能会令人意外!如果你有自定义的 Button React 组件,请考虑返回 <button type="button"> 而不是 <button>。然后,为了明确起见,使用 <button type="submit"> 表示那些应该提交表单的按钮。


使用状态变量控制选择框

<select /> 这样的选择框是 非受控的。即使你 传递一个初始选中的值,例如 <select defaultValue="orange" />,你的 JSX 只指定了初始值,而不是当前值。

要渲染一个 受控的 选择框,请传递 value 属性。React 将强制选择框始终具有你传递的 value 值。通常,你可以通过声明一个 状态变量 来控制选择框:

function FruitPicker() {
const [selectedFruit, setSelectedFruit] = useState('orange'); // Declare a state variable...
// ...
return (
<select
value={selectedFruit} // ...force the select's value to match the state variable...
onChange={e => setSelectedFruit(e.target.value)} // ... and update the state variable on any change!
>
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="orange">Orange</option>
</select>
);
}

如果你希望根据每次选择重新渲染 UI 的某些部分,这将非常有用。

import { useState } from 'react';

export default function FruitPicker() {
  const [selectedFruit, setSelectedFruit] = useState('orange');
  const [selectedVegs, setSelectedVegs] = useState(['corn', 'tomato']);
  return (
    <>
      <label>
        Pick a fruit:
        <select
          value={selectedFruit}
          onChange={e => setSelectedFruit(e.target.value)}
        >
          <option value="apple">Apple</option>
          <option value="banana">Banana</option>
          <option value="orange">Orange</option>
        </select>
      </label>
      <hr />
      <label>
        Pick all your favorite vegetables:
        <select
          multiple={true}
          value={selectedVegs}
          onChange={e => {
            const options = [...e.target.selectedOptions];
            const values = options.map(option => option.value);
            setSelectedVegs(values);
          }}
        >
          <option value="cucumber">Cucumber</option>
          <option value="corn">Corn</option>
          <option value="tomato">Tomato</option>
        </select>
      </label>
      <hr />
      <p>Your favorite fruit: {selectedFruit}</p>
      <p>Your favorite vegetables: {selectedVegs.join(', ')}</p>
    </>
  );
}

陷阱

如果你传递了 value 属性但没有传递 onChange 属性,则将无法选择任何选项。当你通过传递 value 属性来控制选择框时,你强制它始终具有你传递的值。因此,如果你传递状态变量作为 value 属性,但忘记在 onChange 事件处理程序期间同步更新该状态变量,React 将在每次按键后将选择框恢复到你指定的值。

与HTML不同,不支持向单个 <option> 传递 selected 属性。