React实现列表项去重加入Chips及删除Chip返回列表方案
问题解决:列表项选中去重与双向联动更新
问题说明
当前代码存在两个核心问题:
- 重复点击同一列表项会重复生成Chip,未实现选中项去重
- 选中项仍保留在列表中,删除Chip时无法将该项放回列表
解决方案与代码修改
以下是修复后的完整代码,关键改动已标注:
import React, { useState, useEffect } from 'react' import { Typography, Paper, Box } from '@mui/material' import Chip from '@mui/material/Chip'; import SearchInput from '../components/SearchInput'; import DeletableChip from '../components/DeletableChip' import { spiritualPractice } from '../constants'; const Page9 = () => { const [searchQuery, setSearchQuery] = useState(""); const [selected, setSelected] = useState<string[]>([]) // 新增:维护可用列表项状态,初始化为原始数据的浅拷贝 const [availableItems, setAvailableItems] = useState<string[]>([...spiritualPractice]) // 修改:删除Chip时,将项放回可用列表 const onDelete = (item) => () => { setSelected(prev => prev.filter(v => v !== item)); setAvailableItems(prev => [...prev, item]); }; // 修改:选中项时先判断是否已存在,不存在则添加并从可用列表移除 const selectPractice = (item) => { if (!selected.includes(item)) { setSelected(prev => [...prev, item]); setAvailableItems(prev => prev.filter(v => v !== item)); } } useEffect(() => { setSearchQuery(""); }, [selected]) const filterData = (query, data) => { if (!query) { return data; } else { return data.filter((d) => d.toLowerCase().includes(query)); } }; // 修改:基于可用列表进行过滤,只显示未选中的项 const dataFiltered = filterData(searchQuery, availableItems); return ( <div> <Typography variant="h6" mt={2} sx={{ fontWeight: 'bold' }}>Passions</Typography> <Typography variant="body2" my={2} sx={{ fontWeight: 'normal' }}>Let everyone know what you're passionate about, by adding it to your profile.</Typography> <DeletableChip /> <Box sx={{ display: 'flex', flexWrap: 'wrap', width: 'auto'}}> {selected.map((el) => ( <Chip key={el} label={el} onDelete={onDelete(el)} sx={{m:1}}/> ))} </Box> <SearchInput searchQuery={searchQuery} setSearchQuery={setSearchQuery} /> <Paper style={{maxHeight: 200, overflowY: 'auto'}}> {dataFiltered.map((d) => ( <div className="text" style={{ padding: 5, justifyContent: "normal", fontSize: 13, margin: 1, width: "250px", borderWidth: "10px", overflowY:'auto' }} key={d} onClick={()=> selectPractice(d)} > {d} </div> ))} </Paper> </div> ) } export default Page9
关键改动说明
- 选中项去重:在
selectPractice方法中添加!selected.includes(item)判断,确保只有未选中的项才会被添加到Chip列表 - 双向联动更新:
- 新增
availableItems状态存储当前可选择的列表项,初始值为原始数据的浅拷贝(避免修改常量) - 选中项时,从
availableItems中移除该项,保证列表不再显示已选中的内容 - 删除Chip时,将项重新添加回
availableItems,让列表再次显示该项
- 新增
- 过滤数据源调整:将
filterData的数据源从原始spiritualPractice改为availableItems,确保过滤只针对未选中的项
内容的提问来源于stack exchange,提问作者Flo
相关产品推荐
相关产品推荐

