So I have a React component like:
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>
);
}
Continuing on for multiple more selects...
I want it so that when I select one option in any of the select tags, it gets removed as an option in all of the others. If I change the selected option, it then becomes available again in all of the others. Does anyone know how I would be able to do this in React?
You have to use state
to manage the value and share it between two select
s.
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> ); }
Why don't you use state? You can use same datasource for options and also same event handlers for all selects.
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>
);
}
There may be a more elegant way to do this, but my thought was to keep track of which select
have chosen which option with a object called chosenObjects
then filtering results based on that information.
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>
);
}
You can also conditionally disable your empty string valued option
after something is chosen:
<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>
You need to track the state of multiple Select
elements, and then conditionally render the options for each one.
I'll use some bits from the other answers and show how to make it work. Edited to keep the options in the same order.
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>
)
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.