React中搜索筛选器与选择筛选器协同工作异常问题
React 多筛选器与搜索框协同工作问题解决
你当前的问题核心是拆分的两个独立useEffect修改同一个状态,导致筛选逻辑互相冲突:
- 若搜索基于原始
products数组,无法叠加分类、评分筛选的结果; - 若搜索基于已过滤的
filteredProducts,清空搜索框时会基于当前已过滤的数组再次过滤,无法恢复到之前的筛选状态。
解决方案:统一基于原始数组计算所有筛选条件
不要将filteredProducts作为中间过滤载体,每次都从原始products出发,同时应用所有筛选规则(分类、评分、搜索关键词),确保任何条件变化时都重新计算完整结果。
方案一:使用useMemo缓存结果(推荐)
import { useMemo } from 'react'; // 自动根据所有筛选条件计算结果 const filteredProducts = useMemo(() => { return products.filter(product => { // 分类筛选:为空则全部匹配,否则匹配对应分类 const matchesCategory = filter1 === "" || product.category.toLowerCase() === filter1.toLowerCase(); // 评分筛选:为空则全部匹配,否则匹配评分大于等于设定值的商品 const matchesRating = filter2 === "" || Math.floor(product.rating.rate) >= filter2; // 搜索筛选:为空则全部匹配,否则匹配任意字段包含关键词的商品 const matchesSearch = searchValue === "" || Object.values(product) .join("") .toLowerCase() .includes(searchValue.toLowerCase()); // 所有条件需同时满足 return matchesCategory && matchesRating && matchesSearch; }); }, [products, filter1, filter2, searchValue]);
此方案无需手动维护filteredProducts状态,useMemo会自动在依赖项变化时重新计算,避免不必要的重复渲染。
方案二:合并为单个useEffect(状态管理方式)
如果习惯用状态存储筛选结果,可将所有逻辑整合到一个useEffect中,同时保留搜索防抖:
useEffect(() => { // 搜索输入防抖,避免频繁计算 const timeout = setTimeout(() => { const result = products.filter(product => { const matchesCategory = filter1 === "" || product.category.toLowerCase() === filter1.toLowerCase(); const matchesRating = filter2 === "" || Math.floor(product.rating.rate) >= filter2; const matchesSearch = searchValue === "" || Object.values(product) .join("") .toLowerCase() .includes(searchValue.toLowerCase()); return matchesCategory && matchesRating && matchesSearch; }); setFilteredProducts(result); }, 500); return () => clearTimeout(timeout); }, [products, filter1, filter2, searchValue]);
方案优势
- 所有筛选条件并行生效,支持单独使用或任意组合;
- 清空搜索框时,自动恢复到分类、评分筛选后的状态;
- 逻辑单一清晰,避免多个
useEffect之间的状态覆盖冲突; - 基于原始数组计算,不会丢失筛选上下文。
内容的提问来源于stack exchange,提问作者coding-spidy
相关产品推荐
相关产品推荐

