如何实现Select组件选项互斥且取消选择时恢复选项(JavaScript)
解决Select组件选项互斥(选中移除、取消恢复)的问题
需求说明
有4个初始选项列表相同的Select组件,要求:
- 选中某一选项后,该选项从其他Select组件的选项列表中移除,避免重复选择
- 清除Select选择或更换选项时,之前的选项能自动恢复到其他Select的列表中
现有问题
当前实现直接修改了原始选项数组listStaff,导致清除或更换选项时,已移除的选项无法恢复,永久丢失。
解决方案代码
1. 保留原始选项常量
// 原始选项列表,作为常量不修改 const listStaff = [ {id: 1, name: 'John Doe'}, {id: 2, name: 'Walter White'}, {id: 3, name: 'Jesse Pinkman'}, {id: 4, name: 'Saul Goodman'}, {id: 5, name: 'Gus Fring'}, {id: 6, name: 'Skyler White'} ];
2. 维护选中状态数组
// 存储4个Select的选中id,初始化为未选中状态 const [staff, setStaff] = useState([undefined, undefined, undefined, undefined]);
3. 实现选项变更处理函数
const onChangeStaff = (selectedId, index) => { // 创建新数组更新对应位置的选中值,清除时selectedId为undefined const newStaff = [...staff]; newStaff[index] = selectedId; setStaff(newStaff); };
4. 渲染Select组件(动态过滤选项)
{/* 第一个Select */} <Select allowClear placeholder="Choose staff #1" onChange={(e) => onChangeStaff(e, 0)} value={staff[0]} > {listStaff .filter(item => { // 保留当前Select的选中项,排除其他已选中的项 return item.id === staff[0] || !staff.filter(Boolean).includes(item.id); }) .map((item) => ( <Select.Option key={item.id} value={item.id}> {item.name} </Select.Option> ))} </Select> {/* 第二个Select */} <Select allowClear placeholder="Choose staff #2" onChange={(e) => onChangeStaff(e, 1)} value={staff[1]} > {listStaff .filter(item => { return item.id === staff[1] || !staff.filter(Boolean).includes(item.id); }) .map((item) => ( <Select.Option key={item.id} value={item.id}> {item.name} </Select.Option> ))} </Select> {/* 第三个Select */} <Select allowClear placeholder="Choose staff #3" onChange={(e) => onChangeStaff(e, 2)} value={staff[2]} > {listStaff .filter(item => { return item.id === staff[2] || !staff.filter(Boolean).includes(item.id); }) .map((item) => ( <Select.Option key={item.id} value={item.id}> {item.name} </Select.Option> ))} </Select> {/* 第四个Select */} <Select allowClear placeholder="Choose staff #4" onChange={(e) => onChangeStaff(e, 3)} value={staff[3]} > {listStaff .filter(item => { return item.id === staff[3] || !staff.filter(Boolean).includes(item.id); }) .map((item) => ( <Select.Option key={item.id} value={item.id}> {item.name} </Select.Option> ))} </Select>
核心逻辑说明
- 不修改原始数组:始终基于原始
listStaff动态计算每个Select的可用选项,避免数据丢失 - 动态过滤规则:每个Select的选项包含两部分:自己当前选中的项(方便查看和修改)、排除其他所有已选中项后的剩余选项
- 状态驱动更新:当选中或清除选项时,仅更新
staff状态数组,所有Select的选项会自动重新计算,实现选项的动态移除和恢复
内容的提问来源于stack exchange,提问作者ItecStudent
相关产品推荐
相关产品推荐

