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

React年月筛选器无法同时生效的问题求助

问题:React日期筛选器同时按年月筛选不生效

我刚开始学React,给现有项目加筛选功能,项目列表包含ID、标题、数字和日期字段,想要支持按年、按月或同时按年月筛选。目前单独选年或选月都能正常过滤,但同时应用两个筛选器时只有一个生效。

原Expenses组件代码:

function Expenses(props) {
  const [filteredYear, setFilteredYear] = useState("2023");
  const filterChangeFilterYear = (selectedYear) => {
    setFilteredYear(selectedYear);
  };

  const filteredExpensesYear = props.items.filter((expense) => {
    if (filteredYear > 0) {
      return expense.date.getFullYear().toString() === filteredYear;
    } else {
      return 1;
    }
  });


    const [filteredMonth, setFilteredMonth] = useState("12");
    const filterChangeFilterMonth = (selectedMonth) => {
      setFilteredMonth(selectedMonth);
    };
  
    const filteredExpensesMonth = props.items.filter((expense) => {
      if (filteredMonth < 12) {
        return expense.date.getMonth().toString() === filteredMonth;
      } else {
        return 1;
      }
    });

  return (
    <div>
      <Card className="expenses">
        <ExpensesFilterYear
          selected={filteredYear}
          onChangeFilter={filterChangeFilterYear}
        />
        <ExpensesFilterMonth
          onChangeFilter={filterChangeFilterMonth}
        />
        <ExpensesChart expenses={(filteredExpensesMonth && filteredExpensesYear)} /> {/* 这里不生效 */}
        <ExpensesList items={(filteredExpensesYear && filteredExpensesMonth)} /> {/* 这里不生效 */}
      </Card>
    </div>
  );
}

次要代码(筛选器组件):

function ExpensesFilterYear(props) {
  const dropdownChangeHandler = (event) => {
    props.onChangeFilter(event.target.value);
  };

  return (
    <div className='expenses-filter'>
      <div className='expenses-filter__control'>
        <label>expenses for year:</label>
        <select value={props.selected} onChange={dropdownChangeHandler}> 
          <option value='0'>all</option>
          <option value='2022'>2022</option>
          <option value='2023'>2023</option>
          <option value='2024'>2024</option>
          <option value='2025'>2025</option>
        </select>
      </div>
    </div>
  );
};

export default ExpensesFilterYear;
function ExpensesFilterMonth(props) {
  const dropdownChangeHandler = (event) => {
    props.onChangeFilter(event.target.value);
  };

  return (
    <div className="expenses-filter">
      <div className="expenses-filter__control">
        <label>month:</label>
        <select
          value={props.selected}
          onChange={dropdownChangeHandler}
        >
          <option value="12">all</option>
          <option value="0">jan</option>
          <option value="1">feb</option>
          <option value="2">Mar</option>
          <option value="3">may</option>
          <option value="4">apr</option>
          <option value="5">jun</option>
          <option value="6">jul</option>
          <option value="7">aug</option>
          <option value="8">sep</option>
          <option value="9">oct</option>
          <option value="10">nov</option>
          <option value="11">dec</option>
        </select>
      </div>
    </div>
  );
}

export default ExpensesFilterMonth;

我试过把&&改成逗号,但没用,不知道还能试什么。


解决方法

你现在的核心问题是:分开对原始列表做两次过滤,然后用&&传递结果——这在JavaScript里是逻辑运算,不是集合交集,只会返回第一个为真的数组(或者最后一个),根本不会同时应用两个筛选条件。正确的做法是一次过滤同时校验年和月的条件。

修改后的Expenses组件代码:

function Expenses(props) {
  const [filteredYear, setFilteredYear] = useState("2023");
  const filterChangeFilterYear = (selectedYear) => {
    setFilteredYear(selectedYear);
  };

  const [filteredMonth, setFilteredMonth] = useState("12");
  const filterChangeFilterMonth = (selectedMonth) => {
    setFilteredMonth(selectedMonth);
  };

  // 合并年月筛选逻辑,一次过滤完成
  const filteredExpenses = props.items.filter((expense) => {
    // 年份条件:如果选了具体年份则匹配,否则通过
    const yearMatches = filteredYear === "0" 
      ? true 
      : expense.date.getFullYear().toString() === filteredYear;
    
    // 月份条件:如果选了具体月份则匹配,否则通过
    const monthMatches = filteredMonth === "12" 
      ? true 
      : expense.date.getMonth().toString() === filteredMonth;

    // 两个条件都满足才保留该条目
    return yearMatches && monthMatches;
  });

  return (
    <div>
      <Card className="expenses">
        <ExpensesFilterYear
          selected={filteredYear}
          onChangeFilter={filterChangeFilterYear}
        />
        {/* 修复:给月筛选器传递selected属性,保证下拉框选中状态正确 */}
        <ExpensesFilterMonth
          selected={filteredMonth}
          onChangeFilter={filterChangeFilterMonth}
        />
        {/* 直接传递合并过滤后的数组 */}
        <ExpensesChart expenses={filteredExpenses} />
        <ExpensesList items={filteredExpenses} />
      </Card>
    </div>
  );
}

关键修改点说明

  1. 合并过滤逻辑:创建filteredExpenses变量,在同一个filter回调里同时判断年和月的条件,只有两个条件都满足时才返回true,这样就能得到同时符合年月筛选的结果。
  2. 修复月筛选器的props:原代码里ExpensesFilterMonth没有传递selected属性,导致下拉框的选中状态和实际筛选值不匹配,现在补上selected={filteredMonth}。
  3. 简化条件判断:用更清晰的三元表达式替代原有的if-else,让逻辑更易读。

这样修改后,单独选年、单独选月、同时选年月都能正常生效了。

内容的提问来源于stack exchange,提问作者Jacek B.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 23:40:34