内置浏览器的 <select> 组件 让你渲染一个带选项的选择框。
<select>
<option value="someOption">某个选项</option>
<option value="otherOption">另一个选项</option>
</select>参考
<select>
要显示一个选择框,请渲染 内置浏览器的 <select> 组件。
<select>
<option value="someOption">某个选项</option>
<option value="otherOption">另一个选项</option>
</select>Props
<select> 支持所有 通用元素 props。
你可以通过传递 value prop 来将选择框设为受控:
value:一个字符串(对于multiple={true}则为字符串数组)。控制选中了哪个选项。每个值字符串都应匹配<select>内部嵌套的某个<option>的value。
当你传递 value 时,也必须传递一个会更新所传值的 onChange 处理函数。
如果你的 <select> 是非受控的,你可以改为传递 defaultValue prop:
defaultValue:一个字符串(对于multiple={true}则为字符串数组)。指定初始选中的选项。
这些 <select> props 同时适用于非受控和受控选择框:
autoComplete:一个字符串。指定某种可能的自动完成行为。autoFocus:一个布尔值。如果为true,React 会在挂载时聚焦该元素。children:<select>接受<option>、<optgroup>和<datalist>组件作为子元素。只要你的自定义组件最终渲染出允许的组件,也可以传入它们。如果你传入的自定义组件最终渲染<option>标签,那么你渲染的每个<option>都必须有一个value。disabled:一个布尔值。如果为true,选择框将不可交互并会显示为灰暗。form:一个字符串。指定该选择框所属的<form>的id。如果省略,则为最近的父级 form。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 不同,向
<option>传递selected属性是不支持的。请改用<select defaultValue>处理非受控选择框,以及用<select value>处理受控选择框。 - 如果选择框接收到
valueprop,它将被视为受控。 - 选择框不能同时既是受控又是非受控的。
- 选择框在其生命周期内不能在受控和非受控之间切换。
- 每个受控选择框都需要一个
onChange事件处理函数,用于同步更新其底层值。
用法
使用选项显示一个选择框
渲染一个内部包含 <option> 组件列表的 <select>,即可显示一个选择框。给每个 <option> 一个 value,表示要随表单提交的数据。
export default function FruitPicker() { return ( <label> 选择一种水果: <select name="selectedFruit"> <option value="apple">苹果</option> <option value="banana">香蕉</option> <option value="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> 选择一种水果: <select name="selectedFruit"> <option value="apple">苹果</option> <option value="banana">香蕉</option> <option value="orange">橙子</option> </select> </label> <hr /> <label htmlFor={vegetableSelectId}> 选择一种蔬菜: </label> <select id={vegetableSelectId} name="selectedVegetable"> <option value="cucumber">黄瓜</option> <option value="corn">玉米</option> <option value="tomato">番茄</option> </select> </> ); }
提供一个初始选中的选项
默认情况下,浏览器会选中列表中的第一个 <option>。如果想默认选中其他选项,请把该 <option> 的 value 作为 defaultValue 传给 <select> 元素。
export default function FruitPicker() { return ( <label> 选择一种水果: <select name="selectedFruit" defaultValue="orange"> <option value="apple">苹果</option> <option value="banana">香蕉</option> <option value="orange">橙子</option> </select> </label> ); }
export default function FruitPicker() { return ( <label> 选择一些水果: <select name="selectedFruit" defaultValue={['orange', 'banana']} multiple={true} > <option value="apple">苹果</option> <option value="banana">香蕉</option> <option value="orange">橙子</option> </select> </label> ); }
提交表单时读取选择框的值
在选择框外包裹一个 <form>,并在其中放一个 <button type="submit">。它会调用你的 <form onSubmit> 事件处理函数。默认情况下,浏览器会把表单数据发送到当前 URL 并刷新页面。你可以通过调用 e.preventDefault() 来覆盖这种行为。使用 new FormData(e.target) 读取表单数据。
export default function EditPost() { function handleSubmit(e) { // 阻止浏览器重新加载页面 e.preventDefault(); // 读取表单数据 const form = e.target; const formData = new FormData(form); // 你可以直接将 formData 作为 fetch 的 body: fetch('/some-api', { method: form.method, body: formData }); // 你也可以像浏览器默认行为那样,从中生成一个 URL: console.log(new URLSearchParams(formData).toString()); // 你也可以把它当作普通对象来使用。 const formJson = Object.fromEntries(formData.entries()); console.log(formJson); // (!) 这里不包括多选值 // 或者你可以获取一个 name-value 对数组。 console.log([...formData.entries()]); } return ( <form method="post" onSubmit={handleSubmit}> <label> 选择你最喜欢的水果: <select name="selectedFruit" defaultValue="orange"> <option value="apple">苹果</option> <option value="banana">香蕉</option> <option value="orange">橙子</option> </select> </label> <label> 选择你最喜欢的所有蔬菜: <select name="selectedVegetables" multiple={true} defaultValue={['corn', 'tomato']} > <option value="cucumber">黄瓜</option> <option value="corn">玉米</option> <option value="tomato">番茄</option> </select> </label> <hr /> <button type="reset">重置</button> <button type="submit">提交</button> </form> ); }
使用状态变量控制选择框
像 <select /> 这样的选择框是非受控的。即使你传入一个初始选中值,比如 <select defaultValue="orange" />,你的 JSX 也只指定了初始值,而不是当前值。
要渲染一个_受控_选择框,请向它传递 value prop。 React 会强制让选择框始终具有你传入的 value。通常,你会通过声明一个状态变量:来控制选择框:
function FruitPicker() {
const [selectedFruit, setSelectedFruit] = useState('orange'); // 声明一个状态变量...
// ...
return (
<select
value={selectedFruit} // ...强制让选择框的值与状态变量匹配...
onChange={e => setSelectedFruit(e.target.value)} // ...并在任何变化时更新状态变量!
>
<option value="apple">苹果</option>
<option value="banana">香蕉</option>
<option value="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> 选择一种水果: <select value={selectedFruit} onChange={e => setSelectedFruit(e.target.value)} > <option value="apple">苹果</option> <option value="banana">香蕉</option> <option value="orange">橙子</option> </select> </label> <hr /> <label> 选择你最喜欢的所有蔬菜: <select multiple={true} value={selectedVegs} onChange={e => { const options = [...e.target.selectedOptions]; const values = options.map(option => option.value); setSelectedVegs(values); }} > <option value="cucumber">黄瓜</option> <option value="corn">玉米</option> <option value="tomato">番茄</option> </select> </label> <hr /> <p>你最喜欢的水果:{selectedFruit}</p> <p>你最喜欢的蔬菜:{selectedVegs.join(', ')}</p> </> ); }