React博客中如何根据嵌套分类数组过滤文章?
React博客按分类过滤文章解决方案
我来帮你搞定这个过滤逻辑,其实核心思路很清晰,不需要复杂的嵌套filter,我们只需要判断每篇文章是否包含选中的分类标签就行。下面给你两种常用的实现方式:
方式一:直接在渲染时计算过滤结果(推荐)
这种方式不需要额外的useEffect,利用React状态更新自动触发重渲染的特性,代码更简洁直观:
import { useState } from 'react'; // 你的文章数据 const posts = [ { "categories": [{"title": "tag1"}, {"title": "tag2"}, {"title": "tag3"}], "title": "First post" }, { "categories": [{"title": "tag2"}, {"title": "tag3"}, {"title": "tag4"}, {"title": "tag5"}], "title": "Second post" }, { "categories": [{"title": "tag1"}, {"title": "tag3"}, {"title": "tag4"}], "title": "Third post" }, { "categories": [{"title": "tag1"}, {"title": "tag2"}, {"title": "tag4"}, {"title": "tag5"}], "title": "Fourth post" } ]; function Blog() { const [filter, setFilter] = useState('all'); // 计算过滤后的文章列表 const filteredPosts = filter === 'all' ? posts : posts.filter(post => // 检查当前文章的分类中是否包含选中的标签 post.categories.some(category => category.title === filter) ); // 提取所有唯一的分类标签,用于生成下拉选项 const allUniqueTags = [...new Set( posts.flatMap(post => post.categories.map(cat => cat.title)) )]; return ( <div className="blog-container"> {/* 分类选择下拉框 */} <select value={filter} onChange={(e) => setFilter(e.target.value)} className="category-filter" > <option value="all">所有分类</option> {allUniqueTags.map(tag => ( <option key={tag} value={tag}>{tag}</option> ))} </select> {/* 渲染过滤后的文章 */} <div className="posts-list"> {filteredPosts.map(post => ( <article key={post.title} className="post-card"> <h2>{post.title}</h2> {/* 渲染文章其他内容 */} </article> ))} </div> </div> ); } export default Blog;
关键点解释:
posts.filter():遍历所有文章,只保留符合过滤条件的文章post.categories.some():检查当前文章的分类数组中,是否有任意一个分类的title和选中的filter匹配,只要有一个匹配就返回true,这篇文章就会被保留allUniqueTags:通过flatMap把所有文章的分类展开成一维数组,再用Set去重,最后转成数组,确保下拉框里的标签不重复
如果你的文章数据量很大,可以用useMemo优化计算性能,避免每次渲染都重新计算过滤结果:
import { useState, useMemo } from 'react'; // ...其他代码不变 const filteredPosts = useMemo(() => { return filter === 'all' ? posts : posts.filter(post => post.categories.some(category => category.title === filter) ); }, [filter, posts]); // 只有当filter或posts变化时才重新计算
方式二:使用useEffect维护过滤结果状态
如果你更倾向于用useEffect来处理,也可以把过滤后的文章存在单独的状态中:
import { useState, useEffect } from 'react'; const posts = [/* 你的文章数据 */]; function Blog() { const [filter, setFilter] = useState('all'); const [filteredPosts, setFilteredPosts] = useState(posts); useEffect(() => { if (filter === 'all') { // 选择"所有分类"时直接返回全部文章 setFilteredPosts(posts); } else { // 筛选包含当前标签的文章 const result = posts.filter(post => post.categories.some(category => category.title === filter) ); setFilteredPosts(result); } }, [filter, posts]); // 依赖项要包含filter和posts,确保状态变化时重新计算 // 生成唯一标签的逻辑和之前一样 const allUniqueTags = [...new Set( posts.flatMap(post => post.categories.map(cat => cat.title)) )]; return ( {/* 和方式一一样的渲染结构 */} ); }
这种方式适合需要在过滤完成后做额外操作的场景(比如统计筛选后的文章数量),但一般情况下方式一更简洁。
内容的提问来源于stack exchange,提问作者Luke Bennett
相关产品推荐
相关产品推荐

