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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 19:33:24