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

React单表格多条件筛选实现咨询:勾选筛选项后表格数据联动更新问题

React 多条件联合筛选实现方案

核心逻辑是通过数组filter方法叠加多条件校验,未激活的筛选条件自动跳过,仅生效用户勾选/输入的限制规则,实现步骤如下:

1. 前置准备

首先导入React状态钩子,将原始数据源定义为不可变的常量,避免修改原始数据:

import { useState } from 'react';

// 原始数据源,固定不变
const mainArray = [
  {
    id: 1,
    name: "foo",
    city: "dallas",
    category: "one",
    type: "A",
    active: "FALSE",
  },
  {
    id: 2,
    name: "bar",
    city: "dallas",
    category: "one",
    type: "B",
    active: "FALSE",
  },
  {
    id: 3,
    name: "jim",
    city: "san francisco",
    category: "one",
    type: "B",
    active: "TRUE",
  },
  {
    id: 4,
    name: "jane",
    city: "denver",
    category: "two",
    type: "C",
    active: "FALSE",
  },
];

// 提前对各筛选维度的值去重,避免渲染重复的筛选项
const filterOptions = {
  cities: [...new Set(mainArray.map(item => item.city))],
  categories: [...new Set(mainArray.map(item => item.category))],
  types: [...new Set(mainArray.map(item => item.type))],
  activeStatus: [...new Set(mainArray.map(item => item.active))]
}

2. 定义筛选状态

在组件内定义所有筛选相关的状态,存储用户的选择:

function App() {
  // 存储各维度选中的筛选项,用Set结构方便判断存在性、增删元素
  const [selectedCities, setSelectedCities] = useState(new Set());
  const [selectedCategories, setSelectedCategories] = useState(new Set());
  const [selectedTypes, setSelectedTypes] = useState(new Set());
  const [selectedActive, setSelectedActive] = useState(new Set());
  // 存储名称搜索关键词
  const [nameKeyword, setNameKeyword] = useState('');

3. 核心筛选逻辑

计算筛选后的表格数据,多条件同时生效:

const filteredData = mainArray.filter(item => {
    // 城市筛选:如果有选中城市,则需要item的城市在选中集合内,否则不限制
    const matchCity = selectedCities.size === 0 ? true : selectedCities.has(item.city);
    // 分类筛选
    const matchCategory = selectedCategories.size === 0 ? true : selectedCategories.has(item.category);
    // 类型筛选
    const matchType = selectedTypes.size === 0 ? true : selectedTypes.has(item.type);
    // 状态筛选
    const matchActive = selectedActive.size === 0 ? true : selectedActive.has(item.active);
    // 名称筛选:关键词为空则不限制,否则做不区分大小写的模糊匹配
    const matchName = nameKeyword.trim() === '' ? true : item.name.toLowerCase().includes(nameKeyword.toLowerCase());

    // 所有条件同时满足才会被保留
    return matchCity && matchCategory && matchType && matchActive && matchName;
  })

4. 封装筛选项更新方法

简化复选框选中状态切换的逻辑:

// 通用的Set状态更新方法
  const toggleFilter = (setter, value) => {
    setter(prev => {
      const newSet = new Set(prev);
      if (newSet.has(value)) {
        newSet.delete(value);
      } else {
        newSet.add(value);
      }
      return newSet;
    })
  }

5. 渲染部分修改

替换原来重复渲染的筛选项逻辑,表格使用筛选后的数据渲染:

return (
    <div className="App">
      {/* 城市筛选项 */}
      {filterOptions.cities.map(city => (
        <div key={city}>
          <div>
            City : {city} 
            <input 
              type="checkbox" 
              onChange={() => toggleFilter(setSelectedCities, city)}
              checked={selectedCities.has(city)}
            />
          </div>
          <br />
        </div>
      ))}

      {/* 分类筛选项 */}
      {filterOptions.categories.map(cate => (
        <div key={cate}>
          <div>
            Category : {cate} 
            <input 
              type="checkbox" 
              onChange={() => toggleFilter(setSelectedCategories, cate)}
              checked={selectedCategories.has(cate)}
            />
          </div>
          <br />
        </div>
      ))}

      {/* 类型筛选项 */}
      {filterOptions.types.map(type => (
        <div key={type}>
          <div>
            Type : {type} 
            <input 
              type="checkbox" 
              onChange={() => toggleFilter(setSelectedTypes, type)}
              checked={selectedTypes.has(type)}
            />
          </div>
          <br />
        </div>
      ))}

      {/* 状态筛选项 */}
      {filterOptions.activeStatus.map(status => (
        <div key={status}>
          <div>
            Active : {status} 
            <input 
              type="checkbox" 
              onChange={() => toggleFilter(setSelectedActive, status)}
              checked={selectedActive.has(status)}
            />
          </div>
          <br />
        </div>
      ))}

      {/* 名称搜索框 */}
      Name : <input 
        type="text" 
        value={nameKeyword}
        onChange={(e) => setNameKeyword(e.target.value)}
      />
      <br />

      {/* 表格部分,使用筛选后的filteredData渲染 */}
      <table border="5px" align="center">
        <thead>
          <tr>
            <th>ID</th>
            <th>Name</th>
            <th>City</th>
            <th>Category</th>
            <th>Type</th>
            <th>Status</th>
          </tr>
        </thead>
        <tbody>
          {filteredData.map((item, i) => (
            <tr key={i}>
              <td>{item.id}</td>
              <td>{item.name}</td>
              <td>{item.city}</td>
              <td>{item.category}</td>
              <td>{item.type}</td>
              <td>{item.active}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

export default App;

实现说明

  • 所有筛选条件默认不激活,即展示全部数据
  • 多个筛选条件同时勾选时,取交集结果,仅展示同时满足所有条件的数据
  • 筛选项提前做了去重处理,不会出现重复的选项
  • 名称搜索支持不区分大小写的模糊匹配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 14:39:04