如何在 React 中正确更新 <select multiple ...>?
How to correctly update <select multiple ...> in React?
在 React 应用中,您应该控制一个 <select>
。一个 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
的选项采取操作似乎只适用于桌面 - 在 iOS 的 Safari 中,select multiple === true
似乎无法控制。
我觉得这是一个非常基本的问题,但我找不到任何关于它的内容。我不想安装带有预样式组件的整个库,只是为了能够 select 在 <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>
)
}
(虽然这对我来说工作不正常)
对于 select,e.target
给你 options
数组,你可以遍历它得到 selected
选项。使用 map
获取实际值并将它们存储在您的状态中。
select
<select
onChange={handleChangeNormalSelect}
multiple
value={val}
options={options}
>
{options.map(item => {
return <option value={item.value}>{item.label}</option>;
})}
</select>
onChange
...
const [val, setVal] = useState([]);
...
const handleChangeNormalSelect = e => {
const updatedOptions = [...e.target.options]
.filter(option => option.selected)
.map(x => x.value);
console.log("updatedOptions", updatedOptions);
setVal(updatedOptions);
};
...
在 React 应用中,您应该控制一个 <select>
。一个 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
的选项采取操作似乎只适用于桌面 - 在 iOS 的 Safari 中,select multiple === true
似乎无法控制。
我觉得这是一个非常基本的问题,但我找不到任何关于它的内容。我不想安装带有预样式组件的整个库,只是为了能够 select 在 <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>
)
}
(虽然这对我来说工作不正常)
对于 select,e.target
给你 options
数组,你可以遍历它得到 selected
选项。使用 map
获取实际值并将它们存储在您的状态中。
select
<select
onChange={handleChangeNormalSelect}
multiple
value={val}
options={options}
>
{options.map(item => {
return <option value={item.value}>{item.label}</option>;
})}
</select>
onChange
...
const [val, setVal] = useState([]);
...
const handleChangeNormalSelect = e => {
const updatedOptions = [...e.target.options]
.filter(option => option.selected)
.map(x => x.value);
console.log("updatedOptions", updatedOptions);
setVal(updatedOptions);
};
...