You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

关键改动说明

  1. 选中项去重:在selectPractice方法中添加!selected.includes(item)判断,确保只有未选中的项才会被添加到Chip列表
  2. 双向联动更新:
    • 新增availableItems状态存储当前可选择的列表项,初始值为原始数据的浅拷贝(避免修改常量)
    • 选中项时,从availableItems中移除该项,保证列表不再显示已选中的内容
    • 删除Chip时,将项重新添加回availableItems,让列表再次显示该项
  3. 过滤数据源调整:将filterData的数据源从原始spiritualPractice改为availableItems,确保过滤只针对未选中的项

内容的提问来源于stack exchange,提问作者Flo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 14:42:18