NextJS实现作品分类与年份双条件筛选及无结果提示
实现分类与年份的组合筛选及无结果提示
问题背景
基于NextJS开发的作品集项目,已实现分类筛选功能,需要新增年份筛选并支持组合筛选(同时满足分类和年份条件),且在无筛选结果时显示提示信息。
解决方案
一、实现组合筛选
1. 新增年份筛选状态
在WorkPage组件中添加年份状态管理:
const [selectedCat, setSelectedCat] = useState(""); const [selectedYear, setSelectedYear] = useState(""); // 新增年份筛选状态
2. 创建年份筛选组件(FilterYear.js)
// FilterYear.js import works from "@/content/works/data.json" export default function FilterYear({selectedYear, onSelect}) { // 提取所有唯一年份并按倒序排列 const years = Array.from(new Set(works.map(w => w.year))).sort((a, b) => b - a); return ( <div> <ul> <li className={!selectedYear ? "bg-indigo-50 p-2 rounded-md" : "p-2"} onClick={() => onSelect("")} > Все года </li> {years.map((year, i) => { const isSelected = year.toString() === selectedYear return ( <li key={i} className={isSelected ? "bg-indigo-50 p-2 rounded-md" : "p-2"} onClick={() => onSelect(year.toString())} > {year} </li> ) })} </ul> </div> ) }
3. 修改筛选逻辑
替换原有的filteredCat逻辑,同时判断分类和年份条件:
const filteredWorks = work.filter(item => { // 分类匹配规则:无选中分类则全部匹配,否则匹配包含该分类的项 const matchesCat = !selectedCat || item.category.includes(selectedCat); // 年份匹配规则:无选中年份则全部匹配,否则匹配年份完全一致的项 const matchesYear = !selectedYear || item.year.toString() === selectedYear; // 必须同时满足两个条件 return matchesCat && matchesYear; });
4. 在页面中引入年份筛选组件
在WorkPage的导入和渲染部分添加:
// 导入组件 import FilterYear from "@/components/filter-year"; // 页面渲染时,在FilterWork下方添加 <div className="flex gap-4 mb-6"> <FilterWork selectedCat={selectedCat} onSelect={setSelectedCat} /> <FilterYear selectedYear={selectedYear} onSelect={setSelectedYear} /> </div>
二、添加无结果提示
在作品列表渲染区域,判断筛选结果长度,为空时显示提示:
<div className={styles.featuredWorkInner}> {filteredWorks.length === 0 ? ( <p className="text-gray-500 py-8 text-center">未找到内容,请选择其他筛选条件</p> ) : ( filteredWorks.map((workItem) => ( <Work key={workItem.title} item={workItem} /> )) )} </div>
完整修改后的WorkPage代码
import { useState } from "react" import Seo from "@/components/global/seo"; import Work from "../components/work"; import {getAllWork} from "@/lib/getAllData"; import styles from "@/styles/home/featuredWork.module.css" import FilterWork from "@/components/filter-work"; import FilterYear from "@/components/filter-year"; export async function getStaticProps() { const work = getAllWork(); return { props: { work, }, }; } export default function WorkPage({work}) { const [selectedCat, setSelectedCat] = useState(""); const [selectedYear, setSelectedYear] = useState(""); const filteredWorks = work.filter(item => { const matchesCat = !selectedCat || item.category.includes(selectedCat); const matchesYear = !selectedYear || item.year.toString() === selectedYear; return matchesCat && matchesYear; }); return ( <div> <Seo title="Все работы Колтан Леонида" description="Здесь собраны некоторые из работ разработчика Колтан Леонида" ogImageUrl={`http://localhost:3000/api/og?title=Все работы Колтан Леонида&description=Здесь собраны некоторые из работ разработчика Колтан Леонида`} /> <section className='px-6'> <div className='wrapper'> <h1 className='sectionTitle'>Проекты</h1> <div className="flex gap-4 mb-6"> <FilterWork selectedCat={selectedCat} onSelect={setSelectedCat} /> <FilterYear selectedYear={selectedYear} onSelect={setSelectedYear} /> </div> <div className={styles.featuredWorkInner}> {filteredWorks.length === 0 ? ( <p className="text-gray-500 py-8 text-center">未找到内容,请选择其他筛选条件</p> ) : ( filteredWorks.map((workItem) => ( <Work key={workItem.title} item={workItem} /> )) )} </div> </div> </section> </div> ) }
内容的提问来源于stack exchange,提问作者Лео
相关产品推荐
相关产品推荐

