reactjs - 如何在React中正确更新<select multiple ...>?

标签 reactjs select jsx dropdown controlled-component

在 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 的选项采取行动似乎只适用于桌面 - 在 iOS 上的 Safari 中,选择 multiple === true似乎无法控制。

我觉得这是一个非常基本的问题,但我找不到任何相关内容。我不想安装带有预样式组件的整个库,只是为了能够在 <select> 中选择多个选项。在 react 应用程序内。

以下是我尝试过的一些 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>
  )
}

(尽管这对我来说不能正常工作)

最佳答案

对于选择,e.target 为您提供 options 数组,您可以循环通过它获取selected 选项。使用 map 获取实际值并将其存储在您的州中。

选择

   <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);
  };
...

工作中code sample(html multi select) is here

关于reactjs - 如何在React中正确更新<select multiple ...>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61671034/

相关文章:

reactjs - 使用 React Router v4 进行多种布局

mysql - 如何将一行分配到不同的行中,并按其具有的值和创建日期分组?

reactjs - 如何设置 Antd 分隔线颜色

javascript - 如何从 Vuejs 中的 JSX 功能组件发出事件

javascript - ECMAScript 6 箭头函数

javascript - 如何从 Service Worker 对象调用 React 类的函数?

javascript - Redux reducers——改变深度嵌套状态

select - odata - 结合 $expand 和 $select

sql - 在 MySQL 中选择多个唯一行

reactjs - 如何修复 jsx 结束标签 : "unclosed regular expression"? 上的 linting 错误