В приложении React вы должны управлять <select>
. Это очень просто с одним выбором:
const ExampleSelect = () => {
const [value, setValue] = React.useState()
return (
<select
value={value}
onChange={(e) => setValue(e.currentTarget.value)}
>
<option value='foo'>Foo</option>
<option value='bar'>Bar</option>
<option value='baz'>Baz</option>
</select>
)
}
Но когда вы добавляете опору multiple
к <select>
, все становится странно. Функции, переданные в onChange
, которые перебирают параметры и предпринимают действия в зависимости от того, какие из них имеют option.selected === true
, похоже, работают только на рабочем столе - в Safari на iOS, выбор с multiple === true
кажется невозможным контролировать.
Мне кажется, что это действительно базовый c вопрос, но я ничего не могу найти по нему. Я не собираюсь устанавливать целую библиотеку, которая поставляется с предварительно стилизованными компонентами, чтобы иметь возможность выбрать несколько параметров в <select>
внутри приложения реакции.
Вот несколько функций onChange, которые я пробовал:
type Setter = React.Dispatch<React.SetStateAction<string[] | undefined>>
type SelectChange = React.ChangeEvent<HTMLSelectElement>
export const handleMultiSelectChange = <S extends Function = Setter>(
value: string[] | undefined, setter: S
) => (
e: SelectChange
): void => {
const v = e.currentTarget.value
if (value && value.length > 0) {
const index = value.indexOf(v)
if (index >= 0) {
const newValue = value.filter((opt) => opt !== v)
setter(newValue)
} else {
setter([...value, v])
}
} else {
setter([v])
}
}
type Setter = React.Dispatch<React.SetStateAction<string[] | undefined>>
type SelectChange = React.ChangeEvent<HTMLSelectElement>
export const handleChangeMultiple = <S extends Function = Setter>(
value: string[] | undefined = [], setter: S
) => (
event: SelectChange
): void => {
const {options} = event.currentTarget
for (let i = 0, l = options.length; i < l; i += 1) {
const option = options[i]
if (option.selected) {
alert(value.includes(option.value))
if (value.includes(option.value)) {
const index = value.indexOf(option.value)
value.splice(index, 1)
} else {
value.push(option.value)
}
}
}
setter(value)
}
(эти используются вот так:)
const ExampleSelect = () => {
const [value, setValue] = React.useState()
return (
<select
multiple
value={value}
onChange={handleChangeMultiple(value, setValue)}
>
<option value='foo'>Foo</option>
<option value='bar'>Bar</option>
<option value='baz'>Baz</option>
</select>
)
}
(хотя у меня это работает неправильно)