react-select如何避免默认选中项在共用选项的两个下拉框中重复出现
React Select 双下拉框互斥逻辑修复方案
根因分析
- 初始状态未对两个下拉框的可选选项做过滤:仅给两个下拉框设置了默认选中值,初始的
options1和options2直接用了全量犬种数据,没有提前剔除另一个下拉框默认选中的项 - 第一个下拉框的
onChange逻辑错误:当前代码选中第一个下拉框的选项后,给第二个下拉框的可选选项过滤条件是o.firstDropdown === true,和选中项完全无关 - 选项对比逻辑不稳定:直接用
includes判断对象是否存在属于引用对比,后续如果数据源不是同一个引用数组时会失效,建议按唯一的value字段判断 - 变量名拼写错误:全局定义的选项数组名为
dogOptions,组件内引用时写成了options
修复步骤
- 提前计算两个下拉框的默认选中值,作为公共常量复用
- 初始化
options1的时候,直接剔除第二个下拉框的默认选中项;初始化options2的时候,剔除第一个下拉框的默认选中项 - 修正两个下拉框的
onChange逻辑:每次选中值变更时,都用全量数组过滤掉当前下拉框选中的所有项,赋值给另一个下拉框的可选选项 - 统一用
value字段做选项匹配,避免引用对比的问题
修复后完整代码
import React from 'react'; import Select from 'react-select'; export const dogOptions = [ { value: 1, label: "Chihuahua", firstDropdown: true, secondDropdown: false }, { value: 2, label: "Bulldog", firstDropdown: false, secondDropdown: true }, { value: 3, label: "Dachshund", firstDropdown: true, secondDropdown: false }, { value: 4, label: "Akita", firstDropdown: false, secondDropdown: false }, { value: 5, label: "Lab", firstDropdown: false, secondDropdown: false } ]; // 提前提取默认选中值 const defaultFirst = dogOptions.filter(o => o.firstDropdown === true); const defaultSecond = dogOptions.filter(o => o.secondDropdown === true); export default () => { // 初始状态就做互斥过滤 const [options1, setOption1] = React.useState( dogOptions.filter(o => !defaultSecond.some(item => item.value === o.value)) ); const [options2, setOption2] = React.useState( dogOptions.filter(o => !defaultFirst.some(item => item.value === o.value)) ); return ( <> <p>First dropdown</p> <Select isMulti options={options1} defaultValue={defaultFirst} onChange={(selectedList1) => { // 第二个下拉框过滤掉第一个选中的所有项 const newOptions2 = dogOptions.filter(o => !selectedList1.some(selected => selected.value === o.value) ); setOption2(newOptions2); }} /> <div style={{ height: 30 }} /> <p>Second dropdown</p> <Select isMulti options={options2} defaultValue={defaultSecond} onChange={(selectedList2) => { // 第一个下拉框过滤掉第二个选中的所有项 const newOptions1 = dogOptions.filter(o => !selectedList2.some(selected => selected.value === o.value) ); setOption1(newOptions1); }} /> </> ); };
内容的提问来源于stack exchange,提问作者BennKingy
相关产品推荐
相关产品推荐

