<select>
Встроенный в браузер компонент <select>
отвечает за рендер поля выбора с пунктами списка.
<select>
<option value="someOption">Пункт списка</option>
<option value="otherOption">Другой пункт списка</option>
</select>
Справочник
<select>
Чтобы отобразить поле выбора, отрендерите встроенный в браузер компонент <select>
.
<select>
<option value="someOption">Пункт списка</option>
<option value="otherOption">Другой пункт списка</option>
</select>
Пропсы
<select>
поддерживает все пропсы общих HTML-элементов.
Можно сделать поле выбора управляемым, передав проп value
:
value
: строка (или массив строк дляmultiple={true}
). Управляет выбранным вариантом. Значение каждой строкиvalue
соответствует некоторому<option>
, вложенному в<select>
.
При передаче value
, также необходимо передать обработчик onChange
, который будет отвечать за обновление переданного значения.
Если <select>
является неуправляемым, то нужно передать проп defaultValue
:
defaultValue
: строка (или массив строк дляmultiple={true}
). Указывает значение по умолчанию.
Эти пропсы <select>
актуальны для неуправляемых и управляемых полей выбора:
autoComplete
: строка. Указывает одно из возможных поведений автозаполнения.autoFocus
: булево значение. Еслиtrue
, React установит фокус на элемент при монтировании.children
:<select>
принимает компоненты<option>
,<optgroup>
и<datalist>
в качестве дочерних. Вы также можете передать свои собственные компоненты, но только в том случае, если в конечном итоге они рендерят один из вышеперечисленных компонентов. Если ваши компоненты рендерят теги<option>
, то каждый отрендеренный<option>
должен содержатьvalue
.disabled
: булево значение. Еслиtrue
, то поле выбора не будет интерактивным и будет отображаться затемнённым.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, передача атрибута
selected
в<option>
не поддерживается. Вместо этого используется<select defaultValue>
для неуправляемого поля выбора и<select value>
для управляемого. - Если поле выбора принимает проп
value
, то оно будет считаться управляемым. - Поле выбора не может быть одновременно управляемым и неуправляемым.
- Поле выбора не может переключаться между управляемым и неуправляемым состоянием в течении своего жизненного цикла.
- Каждому управляемому полю выбора требуется обработчик событий
onChange
, который синхронно обновляет его исходное состояние.
Применение
Отображение поля выбора с пунктами списка
Для отображения поля выбора используйте список компонентов <option>
внутри тега <select>
. Задайте value
каждому элементу <option>
, чтобы предоставить данные для отправки вместе с формой.
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>
, то свяжите их, передав некоторый ID в <select id>
и <label htmlFor>
. Чтобы избежать конфликтов между несколькими экземплярами одного компонента, сгенерируйте такой ID с помощью хука useId
.
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>
в списке. Чтобы выбрать другой параметр по умолчанию, нужно передать value
этого <option>
в качестве 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> ); }
Включение множественного выбора
Чтобы пользователь мог выбрать несоклько вариантов, нужно передать multiple={true}
в <select>
. В этом случае, если также указать defaultValue
для выбора вариантов по умолчанию, то это должен быть массив.
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('/some-api', { method: form.method, body: formData }); // Вы можете сгенерировать из него URL, как это делает браузер по умолчанию: console.log(new URLSearchParams(formData).toString()); // Вы можете работать с ним, как с обычным объектом. const formJson = Object.fromEntries(formData.entries()); console.log(formJson); // (!) Не включает множественный выбор значений // Или вы можете получить массив пар ключ-значение. 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
. React принудит поле выбора всегда хранить переданное value
. Обычно, управлять полем выбора можно при помощи переменной состояния:
function FruitPicker() {
const [selectedFruit, setSelectedFruit] = useState('orange'); // Объявляем переменную состояния...
// ...
return (
<select
value={selectedFruit} // ...сопоставляем value поля выбора с переменной состояния...
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> </> ); }