[英]Have multiple <select> elements share the same options in React?
所以我有一个 React 组件,如:
export default function ExampleComponent() {
return (
<div>
<select required name="select1">
<option label=" "></option>
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
<option value="option3">Option 3</option>
</select>
<select name="select2">
<option label=" "></option>
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
<option value="option3">Option 3</option>
</select>
</div>
);
}
继续进行多个选择...
我想要它,以便当我在任何选择标签中选择一个选项时,它会作为所有其他选项中的一个选项被删除。 如果我更改选定的选项,它就会在所有其他选项中再次可用。 有谁知道我如何在 React 中做到这一点?
您必须使用state
来管理值并在两个select
之间共享它。
import React, {useState} from 'react' export default function ExampleComponent() { const [value, setValue] = useState('option0') handleChange = (e) => { setValue(e.target.value) } return ( <div> <select value={value} onChange={handleChange}> <option value="option0"></option> <option value="option1">Option 1</option> <option value="option2">Option 2</option> <option value="option3">Option 3</option> </select> <select value={value} onChange={handleChange}> <option value="option0"></option> <option value="option1">Option 1</option> <option value="option2">Option 2</option> <option value="option3">Option 3</option> </select> </div> ); }
你为什么不使用状态? 您可以为选项使用相同的数据源,也可以为所有选择使用相同的事件处理程序。
export default function ExampleComponent() {
state = {
options: [
{
name: 'Option 1',
value: 'option1'
},
{
name: 'Option 2',
value: 'option2'
},
{
name: 'Option 3',
value: 'option3'
}
]
};
onChangeSelect = event => {
// do something
this.setState({
options: this.state.options.filter(
option => option.value !== event.target.value
)
});
};
return (
<div>
<select required name="select1" onChange={onChangeSelect}>
<option label=" "></option>
{this.state.options.map(option => (
<option value={option.value}>{option.name}</option>
))}
</select>
<select name="select2" onChange={onChangeSelect}>
<option label=" "></option>
{this.state.options.map(option => (
<option value={option.value}>{option.name}</option>
))}
</select>
</div>
);
}
可能有一种更优雅的方法来做到这一点,但我的想法是跟踪哪个select
选择了哪个选项,并使用一个名为chosenObjects
的对象,然后根据该信息过滤结果。
import React, {useState} from "react";
export default function ExampleComponent() {
const selectNames = ["select1", "select2"];
const [options] = useState([
{
label: 'Option 1',
value: 'option1'
},
{
label: 'Option 2',
value: 'option2'
},
{
label: 'Option 3',
value: 'option3'
}
]);
const [chosenOptions, setChosenOptions] = useState({});
const isChosenByOther = (optionValue, selectName) => {
for (let key in chosenOptions) {
if (key !== selectName) {
if (chosenOptions[key] === optionValue) {
return true;
}
}
}
return false;
};
const handleChange = (ev) => {
setChosenOptions({...chosenOptions, [ev.target.name]: ev.target.value});
};
return (
<div>
{selectNames.map((name, index) => {
return (
<select name={name} key={index} onChange={handleChange} value={chosenOptions[name] || ''}
required={index === 0}>
<option value=''/>
{options.filter(({value}) => !isChosenByOther(value, name))
.map(({label, value}, oIndex) =>
<option value={value} key={oIndex}>{label}</option>)
}
</select>
)
})}
</div>
);
}
您还option
在选择某些内容后有条件地禁用空字符串值option
:
<div>
{selectNames.map((name, index) => {
return (
<select name={name} key={index} onChange={handleChange} value={chosenOptions[name] || ''}
required={index === 0}>
<option value='' disabled={chosenOptions[name]}>Choose Option</option>
{options.filter(({value}) => !isChosenByOther(value, name))
.map(({label, value}, oIndex) =>
<option value={value} key={oIndex}>{label}</option>)
}
</select>
)
})}
</div>
您需要跟踪多个Select
元素的状态,然后有条件地为每个元素渲染选项。
我将使用其他答案中的一些内容并展示如何使其工作。 编辑以保持选项的顺序相同。
import React, {useState} from "react";
function ExampleComponent() {
const [myState, setMyState] = useState({});
const options = [
{
name: 'Option 1',
value: 'option1'
},
{
name: 'Option 2',
value: 'option2'
},
{
name: 'Option 3',
value: 'option3'
}
]
// list of select names
const selectNames = [
"select1",
"select2"
]
handleChange = (e) => {
// update the value for the given select
myState[e.target.name] = e.target.value
setMyState(myState)
}
const inUseValues = Object.values(myState);
console.log(inUseValues)
// get the options for given name
getOptions = (name) =>
options.filter(option => !inUseValues.includes(option.value) || myState[name]==option.value)
.map(option => (
<option key={option.value} value={option.value}>{option.name}</option>
))
// render all select controls
const selectRender = selectNames.map(name => (
<select key={name} required name="{name}" value={myState[name]} onChange={handleChange}>
<option label=" "></option>
{getOptions(name)}
</select>
))
return (
<div>
{selectRender}
</div>
)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.