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

React多条件过滤器状态的正确改写方法及输入过滤失效问题解决

解决React多条件过滤中输入框删除字符失效的问题

你的问题核心在于过滤逻辑依赖了已经被修改后的activities状态,而非原始数据源allActivities。当你输入字符时,activities会被逐步缩小范围;但删除字符时,你只能在已经过滤后的小数据集里重新筛选,无法恢复到原始的完整数据,所以看起来没有变化。

下面是修复后的代码和思路:

第一步:重构状态与过滤逻辑

我们需要把所有过滤条件(类型勾选状态、搜索关键词、参与者数量)都作为独立状态保存,然后统一基于原始的allActivities进行过滤,而不是每次修改activities本身。

import { useState, useCallback } from 'react';

const [activities, setActivities] = useState(allActivities);
const [checked, setChecked] = useState<string[]>([]);
const [searchKeyword, setSearchKeyword] = useState(''); // 新增搜索关键词状态
const [minParticipants, setMinParticipants] = useState(1); // 重命名变量更清晰

// 统一过滤函数:基于原始数据,整合所有条件
const applyFilters = useCallback(() => {
  let filtered = [...allActivities];

  // 1. 类型过滤:未勾选的类型不显示(按你的需求逻辑,若勾选则隐藏该类型,可根据实际调整)
  filtered = filtered.filter(({ type }) => !checked.includes(type));

  // 2. 关键词过滤
  if (searchKeyword) {
    filtered = filtered.filter(item => 
      item.activity.toLowerCase().includes(searchKeyword.toLowerCase()) // 建议忽略大小写提升体验
    );
  }

  // 3. 参与者数量过滤
  filtered = filtered.filter(item => item.participants >= minParticipants);

  setActivities(filtered);
}, [allActivities, checked, searchKeyword, minParticipants]);

// 组件初始化时执行一次过滤
useEffect(() => {
  applyFilters();
}, [applyFilters]);

第二步:修改事件处理函数

现在各个交互只需要更新对应的条件状态,然后让统一的过滤函数生效即可:

// 类型勾选切换
const switchType = (event: React.ChangeEvent<HTMLInputElement>) => {
  const currentType = event.target.value;
  const newChecked = checked.includes(currentType)
    ? checked.filter(type => type !== currentType)
    : [...checked, currentType];
  setChecked(newChecked);
};

// 输入框搜索
const inputSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
  setSearchKeyword(event.target.value);
};

// 参与者数量过滤
const countSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
  setMinParticipants(Number(event.target.value) || 1); // 处理空输入的默认值
};

第三步:调整渲染为受控组件

确保输入框的显示与状态一致,避免UI和状态不一致的问题:

<Input 
  value={searchKeyword}
  onChange={inputSearch} 
  startAdornment={
    <InputAdornment position="start">
      <SearchIcon />
    </InputAdornment>
  } 
/>
<Input 
  type="number" 
  value={minParticipants}
  onChange={countSearch} 
  startAdornment={
    <InputAdornment position="start" className={classes.participantsTextField} >
      <PersonIcon />
    </InputAdornment>
  } 
/>

额外优化提示

  1. 类型过滤逻辑校验:你原来的逻辑是!checked.includes(type),也就是勾选的类型会被隐藏。如果你的需求是「勾选的类型才显示」,需要改成:

    filtered = filtered.filter(({ type }) => checked.length === 0 || checked.includes(type));
    

    这样当没有勾选任何类型时,会显示所有活动。

  2. 性能优化:使用useCallback包裹applyFilters,避免每次渲染都创建新函数;如果allActivities是外部传入的props,建议用useMemo缓存,减少不必要的过滤触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 04:52:28