React中如何实现数据去重后映射值并正常显示label字段
问题根源
你现在遇到的label不展示、去重失效的问题,来自三个核心错误:
- 去重逻辑完全不生效:
Array.indexOf()判断对象时是比对内存引用地址,选中事件返回的选项对象,和localizedData里定义的原始对象不是同一个引用,所以localizedData.indexOf(element)永远返回-1,和当前遍历的index(从0开始的正整数)永远不可能相等,最终filter返回空数组,后续map自然拿不到任何label字段。 - 组件配置和预期不符:你给MultiSelect设置的
textField="value",但实际想要展示的是label字段,会导致下拉选项显示内容不符合预期。 - 传值不一致:传给父组件的
value字段直接使用了未去重的原始选中值e.target.value,会导致多选框回显重复选项,同时直接修改props.dataItem的写法违反React单向数据流规则,容易触发不可预期的渲染问题。
修复方案
- 去重逻辑改用唯一标识判断:基于你设置的
dataItemKey: 'id'作为唯一键,用findIndex判断重复项,不要直接比对对象引用。 - 修正MultiSelect的
textField配置为label,对齐展示需求。 - 移除冗余的无效for循环代码,不要直接修改props对象,基于去重后的结果生成展示值、回传选中值,同时补全组件的value属性保证编辑态回显正常。
修复后完整代码
import React from 'react'; import { MultiSelect } from '@progress/kendo-react-dropdowns'; export const SymphonyMultiSelectCell = (props) => { const dataItemKey = 'id'; const textField = 'label'; const localizedData = [ { value: 'one', label: 'one', id: 1 }, { value: 'two', label: 'two', id: 2 }, { value: 'three', label: 'three', id: 3 }, { value: 'four', label: 'four', id: 4 }, { value: 'four', label: 'four', id: 4 }, ]; const onChange = (e) => { if (!props.onChange) return; const selectedValues = e.target.value; // 基于唯一id对选中值去重 const uniqueSelected = selectedValues.filter((item, index, arr) => { return arr.findIndex(target => target[dataItemKey] === item[dataItemKey]) === index; }); // 拼接label生成单元格展示文本 const displayText = uniqueSelected.map(item => item[textField]).join(','); // 新建dataItem副本,避免直接修改props const updatedDataItem = { ...props.dataItem, [props.field]: displayText }; props.onChange({ dataIndex: 0, dataItem: updatedDataItem, field: props.field, syntheticEvent: e.syntheticEvent, value: uniqueSelected, // 回传去重后的值供组件回显 tabIndex: 0, }); }; // 单元格进入编辑态时,把存储的逗号分隔文本转回选项对象供多选组件回显 const selectValue = props.dataItem[props.field] ? props.dataItem[props.field].split(',').map(label => { return localizedData.find(item => item.label === label) }).filter(Boolean) : []; return ( <td> <MultiSelect data={localizedData} textField={textField} dataItemKey={dataItemKey} onChange={onChange} value={selectValue} /> </td> ); };
补充优化:如果你的数据源
localizedData本身就存在重复项(比如示例里id为4的four出现了两次),也可以先对数据源本身做一次去重再传给MultiSelect,从源头避免重复选项可选。
内容的提问来源于stack exchange,提问作者Jordan
相关产品推荐
相关产品推荐

