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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 15:42:35