在 React 中使用多个选项从 <select> 中检索值

Retrieving value from <select> with multiple option in React

React 为 select 框设置哪个选项 selected 的方法是在 <select> 本身上设置一个特殊的 value 道具,对应于您希望 select 编辑的 <option> 元素的 value 属性。对于 multiple select 这个道具可以接受一个数组。

现在因为这是一个特殊属性,我想知道 检索 同一选项数组中的 selected 选项的规范方法是什么-values-structure 当用户更改内容时(因此我可以通过回调将其传递给父组件等),因为可能相同的 value 属性 在 [=30= 上不可用]元素。

举个例子,对于一个文本字段,你会做这样的事情(JSX):

var TextComponent = React.createClass({
  handleChange: function(e) {
    var newText = e.target.value;
    this.props.someCallbackFromParent(newText);
  },
  render: function() {
    return <input type="text" value={this.props.someText} onChange={this.handleChange} />;
  }
});

对于这个多个 select 组件,替换 ??? 的等效项是什么?

var MultiSelectComponent = React.createClass({
  handleChange: function(e) {
    var newArrayOfSelectedOptionValues = ???;
    this.props.someCallbackFromParent(newArrayOfSelectedOptionValues);
  },
  render: function() {
    return (
      <select multiple={true} value={this.props.arrayOfOptionValues} onChange={this.handleChange}>
        <option value={1}>First option</option>
        <option value={2}>Second option</option>
        <option value={3}>Third option</option>
      </select>
    );
  }
});

与您在其他任何地方所做的方式相同,因为您正在使用真实的 DOM 节点作为更改事件的目标:

handleChange: function(e) {
  var options = e.target.options;
  var value = [];
  for (var i = 0, l = options.length; i < l; i++) {
    if (options[i].selected) {
      value.push(options[i].value);
    }
  }
  this.props.someCallback(value);
}

以下对我有用

var selectBoxObj = React.findDOMNode(this.refs.selectBox)
var values = $(selectBoxObj).val()

如果您想使用 ref,您可以像这样获得选定的值:

var select = React.findDOMNode(this.refs.selectRef); 
var values = [].filter.call(select.options, function (o) {
      return o.selected;
    }).map(function (o) {
      return o.value;
    });

2018 ES6更新

  let select = this.refs.selectRef;
  let values = [].filter.call(select.options, o => o.selected).map(o => o.value);

如果您想在填写表格时跟踪所选选项:

handleChange(e) {
    // assuming you initialized the default state to hold selected values
    this.setState({
        selected:[].slice.call(e.target.selectedOptions).map(o => {
            return o.value;
        });
    });
}

selectedOptions 是一个类似数组的 collection/list 元素,与 DOM 相关。选择选项值时,您可以在事件目标对象中访问它。 Array.prototype.slicecall 允许我们为新状态创建它的副本。您还可以使用引用以这种方式访问​​值(以防您没有捕获事件),这是该问题的另一个答案。

另一种方法:

handleChange({ target }) {
    this.props.someCallback(
       Array.prototype.slice.call(target.selectedOptions).map(o => o.value)
    )
}

最简单的方法...

handleChange(evt) {
  this.setState({multiValue: [...evt.target.selectedOptions].map(o => o.value)}); 
}

试试这个:

dropdownChanged = (event) => {
    let obj = JSON.parse(event.target.value);
    this.setState(
        {
            key: obj.key,
            selectedName: obj.name,
            type: obj.type
        });
}


<select onChange={this.dropdownChanged} >
<option value={JSON.stringify({ name: 'name', key: 'key', type: "ALL" })} >All Projetcs and Spaces</option></select>

使用 Array.from()e.target.selectedOptions 您可以执行受控的 select-multiple:

handleChange = (e) => {
  let value = Array.from(e.target.selectedOptions, option => option.value);
  this.setState({values: value});
}

target.selectedOptions return 一个 HTMLCollection

https://codepen.io/papawa/pen/XExeZY

您实际上可以在目标中找到 selectedOptions...无需遍历所有选项。假设您想将值发送到作为道具传递给组件的 onChange 函数:您可以在多个 select.

onChange 上使用以下函数
onSelectChange = (e) => {
    const values = [...e.target.selectedOptions].map(opt => opt.value);
    this.props.onChange(values);
  };

在这个话题上花了很多时间,看到我们现在主要使用的是钩子,新手可能从来没有在 reactjs 中处理过 类。我决定更新此答案,以便人们可以轻松处理使用 vanilla javascript 和 ES6 的问题。我还包括了一个 link 到 codesandbox 以便人们可以使用代码并将其修改为他们的应用程序。

这是代码,它有过多的控制台日志,因此人们可以弄清楚代码中正在做什么以及它是如何做的。

import "./styles.css"
import {useRef} from 'react'


export default function App() {

  const handleSubmit = async(e) => {
    e.preventDefault()
    let selected = [...recipeRef.current.options]
                .filter(option => option.selected)
                .map(option => option.value)
    console.log(new Date(), ' recipeType: ', selected)
    console.log(new Date(), 'with ref: ', [...recipeRef.current.options]);
    [...recipeRef.current.options].map(option => console.log(option,'; ',option.selected))
    console.log([...recipeRef.current.options].filter(option => option.selected))
    console.log([...recipeRef.current.options].filter(option=>option.selected).map(option => option.value))
  }
  const recipeRef = useRef()

  return (
    <div className="App">
      <h1>Hello CodeSandbox example for select Multiple by Julio Spinelli</h1>
      <form onSubmit={handleSubmit}>
          <div className="mb-6">
              <label htmlFor="text" className="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">Name of the Recipe</label>
              <input type="text" id="text" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required ></input>
          </div>
          <div className="mb-6">
              <label htmlFor="recipeType" className="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">Recipe Type</label>
              {/* <input type="text" id="text" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required onChange={(e)=>{setRecipeType(e.target.value)}} value={recipeType}></input> */}
              <select name="recipeType" id="recipeType" ref={recipeRef} multiple={true} size={3}> {/* Step 2 - Add the reference to `select` element */}
                <option value="unselected">unselected</option>
                <option value="Grill">Grill</option>
                <option value="Steak">Steak</option>
                <option value="Pizza">Pizza</option>
              </select>
          </div>
          <div className="flex items-start mb-6">
              <div className="flex items-center h-5">
              <input id="remember" aria-describedby="remember" type="checkbox" className="w-4 h-4 bg-gray-50 rounded border border-gray-300 focus:ring-3 focus:ring-blue-300 dark:bg-gray-700 dark:border-gray-600 dark:focus:ring-blue-600 dark:ring-offset-gray-800" ></input>
              </div>
              <div className="ml-3 text-sm">
              <label htmlFor="remember" className="font-medium text-gray-900 dark:text-gray-300">Recipe uploaded?</label>
              </div>
          </div>
          <button type="submit" className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Save</button>
      </form>
    </div>
  )
}