如何在NextJS中正确实现文章分类筛选与分页功能
解决Next.js中文章筛选与分页的联动问题
你当前的代码核心问题是分页操作直接基于原始articles数组,没有和筛选后的结果联动,导致筛选后分页逻辑依然沿用全部文章的计算。正确的逻辑是先筛选文章,再对筛选后的结果执行分页,同时还要处理分类切换时的页码重置,避免出现无内容的无效页码。
具体修改步骤
1. 调整分页数据源
将分页操作的数据源从原始articles替换为筛选后的filteredArticles,确保分页只针对当前选中分类下的文章:
// 原代码 // const paginatePosts = paginate(articles, currentPage, pageSize, selectedTag); // 修改后 const paginatePosts = paginate(filteredArticles, currentPage, pageSize);
注:如果你的paginate函数不需要selectedTag参数,直接移除即可——筛选逻辑已经提前完成,分页无需再依赖分类标签。
2. 更新分页组件的总条目数
让分页器基于筛选后的文章数量计算总页数,避免出现“总页数与实际内容不匹配”的问题:
// 原代码 // items={articles.length} // 修改后 items={filteredArticles.length}
3. 分类切换时重置页码
切换分类后自动回到第1页,防止用户停留在超出筛选结果总页数的页码上(比如原文章有12条在第2页,筛选后只剩3条,此时第2页会显示空内容):
// 在Index组件中新增分类切换处理函数 const handleTagChange = (tag) => { setSelectedTag(tag); setCurrentPage(1); router.push(`?page=1`, undefined, { shallow: true }); };
然后将Category组件的setSelectedTag替换为这个新函数:
<Category tag={tag} key={tag} selectedTag={selectedTag} setSelectedTag={handleTagChange} // 替换为新函数 onPageChange={handlePageChange} />
修改后的完整Index组件代码
export default function Index({ articles, categories }) { const [selectedTag, setSelectedTag] = useState<string>(null); const filteredArticles = filterArticles(articles, selectedTag); const articleItems = [ <Image className="h-full w-full" src={card1} alt="teste" />, <Image className="h-full w-full" src={card2} alt="teste" />, <Image className="h-full w-full" src={card3} alt="teste" />, <Image className="h-full w-full" src={card4} alt="teste" />, <Image className="h-full w-full" src={card1} alt="teste" />, ]; const [currentPage, setCurrentPage] = useState(1); const pageSize = 6; const router = useRouter(); // 处理分类切换,自动重置页码 const handleTagChange = (tag) => { setSelectedTag(tag); setCurrentPage(1); router.push(`?page=1`, undefined, { shallow: true }); }; const handlePageChange = (page) => { setCurrentPage(page); router.push(`?page=${page}`, undefined, { shallow: true }); }; // 基于筛选后的文章执行分页 const paginatePosts = paginate(filteredArticles, currentPage, pageSize); return ( <Layout> <HeroHeader /> <div className="flex flex-wrap justify-center gap-4 pt-8 dark:bg-slate-900 "> {categories.map((tag) => ( <Category tag={tag} key={tag} selectedTag={selectedTag} setSelectedTag={handleTagChange} onPageChange={handlePageChange} /> ))} </div> <Container> <div> <div className="my-8 text-3xl font-bold text-gray-900 dark:text-gray-100 "> {!selectedTag ? "Сүүлд нийтэлсэн" : `${selectedTag}`} </div> <ArticleList articles={paginatePosts} /> <BlogPagination items={filteredArticles.length} pageSize={pageSize} currentPage={currentPage} onPageChange={handlePageChange} /> </div> </Container> </Layout> ); }
额外说明
- 如果你的
paginate函数原本设计为同时处理筛选和分页,现在可以简化它的逻辑——只需要接收数组、当前页码、每页数量三个参数即可,筛选逻辑已经提前完成。 - 修改后,筛选和分页会完全联动:切换分类自动回到第一页,分页器显示的总页数匹配当前分类的文章数量,列表仅展示当前页的筛选后内容。
内容的提问来源于stack exchange,提问作者Tugulduroch
相关产品推荐
相关产品推荐

