React中如何实现基于多标签数组的食谱数据过滤?
解决React食谱数据多标签过滤问题
修改后的过滤函数代码
const [cuisineInput, setCuisineInput] = useState(""); const [cuisineFilter, setCuisineFilter] = useState<Filter[]>([]); const [filteredResults, setFilteredResults] = useState<any>([]); // 初始值设为空数组更合理 const filterDataByCuisine = useCallback(() => { // 无过滤标签时返回全部数据 if (cuisineFilter.length === 0) { setFilteredResults(data?.hits || []); return; } // 提取过滤标签并统一转为小写,消除大小写差异 const filterLabels = cuisineFilter.map(el => el.label.toLowerCase()); const filteredData = data?.hits.filter(({ recipe }) => { // 将食谱的菜系类型转为小写数组,保证匹配一致性 const recipeCuisines = recipe.cuisineType.map(cuisine => cuisine.toLowerCase()); // 匹配逻辑:食谱包含任意一个过滤标签则保留("或"逻辑) return filterLabels.some(label => recipeCuisines.includes(label)); }) || []; setFilteredResults(filteredData); }, [cuisineFilter, data]);
关键修改说明
- 空过滤处理:当
cuisineFilter为空数组时,直接返回全部食谱数据,避免无标签时出现空结果。 - 大小写统一:将过滤标签和食谱菜系都转为小写,解决大小写不匹配导致的过滤失效问题(比如"Italian"和"italian"视为同一菜系)。
- 正确的多标签匹配逻辑:
- 用
Array.some()实现任意匹配:只要食谱包含过滤数组中的任意一个标签,就保留该食谱(这是多数场景的需求)。 - 如果需要全部匹配(食谱必须包含所有过滤标签),只需把
some()替换为every()即可:return filterLabels.every(label => recipeCuisines.includes(label));
- 用
- 安全的可选链调用:用
data?.hits替代强制非空断言data!.hits,避免data为null/undefined时抛出运行时错误。
额外优化建议
- 把
filteredResults的初始值从null改为空数组[],这样UI渲染时无需额外处理null的情况,更符合数组类型的使用习惯。 - 可以给
filteredResults添加更具体的类型注解,替代any,提升代码的类型安全性。
内容的提问来源于stack exchange,提问作者Jack Rackham
相关产品推荐
相关产品推荐

