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

Next.js 14项目中如何通过Strapi实现单/多分类筛选?

实现Next.js 14 + Strapi 博客分类筛选方案

1. 明确组件分工与类型

  • 页面组件(page.js):保持服务端组件,负责根据URL参数获取对应分类的博客数据。
  • 分类按钮组件(CategoryFilters.jsx):改为客户端组件(添加'use client'指令),处理点击交互并更新URL参数。
  • 博客列表组件(BlogList.jsx):可作为服务端/客户端组件,接收博客数据并渲染。

2. 修改fetchBlogs函数,支持分类筛选参数

Strapi的过滤查询语法为filters[字段名][$eq]=值,我们需要把分类参数转换成对应的查询字符串:

const fetchBlogs = async (category) => {
  const reqOptions = {
    headers: {
      Authorization: `Bearer ${process.env.API_TOKEN}`,
    },
  };
  
  // 构建查询参数:如果有分类则添加过滤条件,否则只保留populate=*
  let queryParams = 'populate=*';
  if (category) {
    queryParams += `&filters[category][$eq]=${encodeURIComponent(category)}`;
  }

  const request = await fetch(`${config.api}/api/blogs?${queryParams}`, reqOptions);
  const response = await request.json();
  return response;
};

3. 改造页面组件,根据URL参数获取对应数据

在服务端页面组件中,通过searchParams获取当前选中的分类,传递给fetchBlogs:

// app/blogs/page.js
import fetchBlogs from '@/lib/fetchBlogs';
import CategoryFilters from '@/components/CategoryFilters';
import BlogList from '@/components/BlogList';

export default async function BlogsPage({ searchParams }) {
  // 从URL的searchParams中获取当前分类,默认空(显示全部)
  const selectedCategory = searchParams?.category || '';
  const blogs = await fetchBlogs(selectedCategory);

  return (
    <div className="container">
      {/* 传递当前选中的分类给按钮组件,用于高亮 */}
      <CategoryFilters activeCategory={selectedCategory} />
      <BlogList blogs={blogs.data} />
    </div>
  );
}

4. 实现分类按钮客户端组件

使用Next.js的useRouter或useSearchParams来更新URL的category参数,触发页面重新获取数据:

// components/CategoryFilters.jsx
'use client';

import { useRouter, useSearchParams } from 'next/navigation';

// 假设分类列表从Strapi获取,或者硬编码(实际项目建议从Strapi获取分类数据)
const categories = ['前端', '后端', '设计', '产品'];

export default function CategoryFilters({ activeCategory }) {
  const router = useRouter();
  const searchParams = useSearchParams();

  const handleFilterClick = (category) => {
    const newSearchParams = new URLSearchParams(searchParams);
    if (category === activeCategory) {
      // 点击已选中的分类,移除筛选条件(显示全部)
      newSearchParams.delete('category');
    } else {
      // 设置选中的分类
      newSearchParams.set('category', category);
    }
    // 更新URL,触发服务端组件重新获取数据
    router.push(`/blogs?${newSearchParams.toString()}`);
  };

  return (
    <div className="filter-buttons">
      {categories.map((cat) => (
        <button
          key={cat}
          onClick={() => handleFilterClick(cat)}
          className={`filter-btn ${activeCategory === cat ? 'active' : ''}`}
        >
          {cat}
        </button>
      ))}
    </div>
  );
}

5. 可选:从Strapi动态获取分类列表

如果分类是在Strapi中维护的,可在页面组件中额外获取分类数据,传递给按钮组件:

// 在BlogsPage中添加
const fetchCategories = async () => {
  const reqOptions = {
    headers: {
      Authorization: `Bearer ${process.env.API_TOKEN}`,
    },
  };
  const res = await fetch(`${config.api}/api/categories`, reqOptions);
  return res.json();
};

// 同时获取博客和分类数据
const [blogsRes, categoriesRes] = await Promise.all([
  fetchBlogs(selectedCategory),
  fetchCategories()
]);

// 传递给组件
<CategoryFilters 
  activeCategory={selectedCategory} 
  categories={categoriesRes.data.map(cat => cat.attributes.name)} 
/>

关键调整点总结

  • 客户端组件标记:分类按钮组件必须加'use client',因为涉及交互事件。
  • Strapi查询语法:用filters[category][$eq]=分类值实现精确匹配筛选,如需模糊匹配可改用$contains。
  • URL参数传递:通过searchParams在服务端组件和客户端组件间传递筛选状态,保证刷新页面后筛选状态不丢失。
  • 路由更新:使用router.push更新URL参数,触发服务端组件重新执行fetchBlogs获取对应数据。

内容的提问来源于stack exchange,提问作者mdnc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:28:22