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> ); }
关键修改点说明
- 合并过滤逻辑:创建
filteredExpenses变量,在同一个filter回调里同时判断年和月的条件,只有两个条件都满足时才返回true,这样就能得到同时符合年月筛选的结果。 - 修复月筛选器的props:原代码里
ExpensesFilterMonth没有传递selected属性,导致下拉框的选中状态和实际筛选值不匹配,现在补上selected={filteredMonth}。 - 简化条件判断:用更清晰的三元表达式替代原有的
if-else,让逻辑更易读。
这样修改后,单独选年、单独选月、同时选年月都能正常生效了。
内容的提问来源于stack exchange,提问作者Jacek B.
相关产品推荐
相关产品推荐

