如何在React中使用MUI Select Chip多选筛选标签?
多标签筛选解决方案(基于Material-UI Select Chip)
预处理图书数据
先把每个图书的tags字符串转为数组,避免字符串匹配的局限性,同时处理可能存在的空格:
const books = [ {id: 'AjRzfMxbfJMphK144DIAr', title: 'javascript', tags: 'code,programining', notes: "This book is a must to", createdAt: 1671459053853}, {id: 'kvdo7HrLr2GeOUX9j4qLq', title: 'css', tags: 'css,code', notes: " mo…his book is a must to have", createdAt: 1671459781356}, {id: 'qQLcIV0sm_AQmdiJgrTpN', title: 'reactjs', tags: 'html,reactjs', notes: "JavaScript's most frequently…nterview ", createdAt: 1671464489642}, {id: 'x1wqP1PV73R35JvGX7lwh', title: 'nodejs', tags: 'html,css', notes: "Colleuently…nave", createdAt: 1671468792674} ].map(book => ({ ...book, tags: book.tags.split(',').map(tag => tag.trim()) // 拆分标签并去除首尾空格 }));
多标签筛选逻辑
假设通过Material-UI Select Chip组件获取到选中标签数组selectedTags,以下是两种常用筛选逻辑:
1. 匹配任意一个选中标签
只要图书标签包含至少一个选中标签就保留:
const filteredBooks = books.filter(book => { return selectedTags.length === 0 ? true // 无选中标签时显示全部 : selectedTags.some(tag => book.tags.includes(tag)); });
2. 匹配所有选中标签
图书标签必须包含所有选中标签才会被保留:
const filteredBooks = books.filter(book => { return selectedTags.length === 0 ? true // 无选中标签时显示全部 : selectedTags.every(tag => book.tags.includes(tag)); });
整合Material-UI组件的完整示例
import { useState } from 'react'; import { Select, Chip, MenuItem, Box } from '@mui/material'; export default function BookTagFilter() { const [selectedTags, setSelectedTags] = useState([]); // 预处理后的图书数据 const books = [ {id: 'AjRzfMxbfJMphK144DIAr', title: 'javascript', tags: 'code,programining', notes: "This book is a must to", createdAt: 1671459053853}, {id: 'kvdo7HrLr2GeOUX9j4qLq', title: 'css', tags: 'css,code', notes: " mo…his book is a must to have", createdAt: 1671459781356}, {id: 'qQLcIV0sm_AQmdiJgrTpN', title: 'reactjs', tags: 'html,reactjs', notes: "JavaScript's most frequently…nterview ", createdAt: 1671464489642}, {id: 'x1wqP1PV73R35JvGX7lwh', title: 'nodejs', tags: 'html,css', notes: "Colleuently…nave", createdAt: 1671468792674} ].map(book => ({ ...book, tags: book.tags.split(',').map(tag => tag.trim()) })); // 提取所有去重的可选标签 const allTags = [...new Set(books.flatMap(book => book.tags))]; // 处理标签选择变更 const handleChange = (event) => { setSelectedTags(event.target.value); }; // 执行筛选(这里用“任意匹配”逻辑,可替换为every实现“全匹配”) const filteredBooks = books.filter(book => { return selectedTags.length === 0 ? true : selectedTags.some(tag => book.tags.includes(tag)); }); return ( <Box sx={{ width: 300, marginBottom: 2 }}> <Select multiple value={selectedTags} onChange={handleChange} renderValue={(selected) => ( <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}> {selected.map((value) => ( <Chip key={value} label={value} /> ))} </Box> )} > {allTags.map((tag) => ( <MenuItem key={tag} value={tag}> {tag} </MenuItem> ))} </Select> {/* 展示筛选后的图书列表 */} <Box sx={{ marginTop: 2 }}> {filteredBooks.map(book => ( <div key={book.id} style={{ marginBottom: '1rem' }}> <h4>{book.title}</h4> <p>标签:{book.tags.join(', ')}</p> </div> ))} </Box> </Box> ); }
核心注意点
- 预处理标签时去除空格,避免因格式问题导致匹配失败(比如
'code'和' code'无法匹配)。 - 空选中状态下返回全部图书,保证初始页面的完整性。
- 可根据业务需求切换
some()和every(),实现不同的筛选规则。
内容的提问来源于stack exchange,提问作者Aman Shukla
相关产品推荐
相关产品推荐

