React中如何基于多选下拉框实现数据多条件同时过滤?
多条件同时过滤数据集的解决方案
问题背景
现有如下结构的数据集:
const data = [ { dealId: 1, name: "deal 1", funding_type: "D", category: "Industrials", status: "Funding", topic: "Latest" }, { dealId: 2, name: "deal 2", funding_type: "E", category: "Financials", status: "Launching", topic: "Most Funded" }, // ... 更多数据 ]
设置了对应category、funding_type、status、topic的四个筛选下拉框,期望实现多条件叠加过滤,但当前代码仅支持单次过滤单个条件,需要调整实现逻辑。
解决方案
核心思路是集中管理所有筛选条件的状态,每次过滤都基于原始数据集和所有当前生效的条件进行校验,而非仅依赖单个条件。
1. 添加筛选条件状态
用useState保存四个筛选条件的当前值,初始值可设为空(或对应下拉框的"全部"选项值):
const [filters, setFilters] = useState({ category: "", type: "", status: "", topic: "" });
2. 编写多条件过滤函数
遍历所有筛选条件,仅当条件有有效值时才进行匹配,无值的条件不参与过滤(等价于全选):
const applyFilters = () => { return data.filter(item => { // 校验category条件 const matchesCategory = !filters.category || item.category === filters.category; // 校验funding_type条件(对应type筛选) const matchesType = !filters.type || item.funding_type === filters.type; // 校验status条件 const matchesStatus = !filters.status || item.status === filters.status; // 校验topic条件 const matchesTopic = !filters.topic || item.topic === filters.topic; // 所有条件都满足才保留 return matchesCategory && matchesType && matchesStatus && matchesTopic; }); };
3. 修改下拉框的 onChange 事件
每个下拉框变化时,更新对应的筛选条件状态:
const handleFilterChange = (value, type) => { setFilters(prev => ({ ...prev, [type]: value })); };
4. 自动触发过滤
用useEffect监听筛选条件的变化,当任何条件更新时自动重新过滤数据:
const [filteredData, setFilteredData] = useState([]); useEffect(() => { setFilteredData(applyFilters()); }, [filters]); // 依赖filters,条件变化时重新执行
完整修改后的代码示例
import { useState, useEffect } from "react"; const data = [ { dealId: 1, name: "deal 1", funding_type: "D", category: "Industrials", status: "Funding", topic: "Latest" }, { dealId: 2, name: "deal 2", funding_type: "E", category: "Financials", status: "Launching", topic: "Most Funded" }, // 更多数据... ]; // 假设的下拉选项数据,根据实际情况调整 const categoryOptions = [/* 选项数据 */]; const typeOptions = [/* 选项数据 */]; const statusOptions = [/* 选项数据 */]; const topicOptions = [/* 选项数据 */]; export default function App() { const [filters, setFilters] = useState({ category: "", type: "", status: "", topic: "" }); const [filteredData, setFilteredData] = useState([]); const applyFilters = () => { return data.filter(item => { const matchesCategory = !filters.category || item.category === filters.category; const matchesType = !filters.type || item.funding_type === filters.type; const matchesStatus = !filters.status || item.status === filters.status; const matchesTopic = !filters.topic || item.topic === filters.topic; return matchesCategory && matchesType && matchesStatus && matchesTopic; }); }; useEffect(() => { setFilteredData(applyFilters()); }, [filters]); const handleFilterChange = (value, type) => { setFilters(prev => ({ ...prev, [type]: value })); }; return ( <div className="app"> {/* Category 筛选框 */} <select className="input-field cursor-pointer" onChange={(e) => handleFilterChange(e.target.value, "category")} value={filters.category} > <option value="">全部分类</option> {categoryOptions.map((opt) => ( <option value={opt.value} key={opt.value}> {opt.placeholder} </option> ))} </select> {/* Type(funding_type)筛选框 */} <select className="input-field cursor-pointer" onChange={(e) => handleFilterChange(e.target.value, "type")} value={filters.type} > <option value="">全部类型</option> {typeOptions.map((opt) => ( <option value={opt.value} key={opt.value}> {opt.placeholder} </option> ))} </select> {/* Status 筛选框 */} <select className="input-field cursor-pointer" onChange={(e) => handleFilterChange(e.target.value, "status")} value={filters.status} > <option value="">全部状态</option> {statusOptions.map((opt) => ( <option value={opt.value} key={opt.value}> {opt.placeholder} </option> ))} </select> {/* Topic 筛选框 */} <select className="input-field cursor-pointer" onChange={(e) => handleFilterChange(e.target.value, "topic")} value={filters.topic} > <option value="">全部主题</option> {topicOptions.map((opt) => ( <option value={opt.value} key={opt.value}> {opt.placeholder} </option> ))} </select> {/* 过滤结果展示 */} <div className="results"> {filteredData.length > 0 ? ( filteredData.map((d) => ( <div key={d.dealId}>{d.name}</div> )) ) : ( <div>暂无匹配数据</div> )} </div> </div> ); }
关键说明
- 集中状态管理:所有筛选条件存在同一个state中,确保每次过滤能获取到全部生效条件
- 条件校验逻辑:每个条件判断时先检查是否有值,无值则直接返回true(不限制该条件),多个条件同时满足才保留数据
- 自动过滤:通过
useEffect监听筛选条件变化,无需手动在每个下拉框的onChange中调用过滤函数,逻辑更简洁
内容的提问来源于stack exchange,提问作者Kaung Khant Zaw
相关产品推荐
相关产品推荐

