Hello everyone I have a project on NextJS. There is a portfolio of works that is generated from json.
[
{
"title": "Плагин WordPress для Рекомендательного виджета Яндекса",
"image": "/images/works/yk.jpg",
"year": 2022,
"category": "WordPress",
"link": "https://188.ru/",
"description": "Заказчик использует на некоторых сайтах виджет рекомендаций от Яндекса, который позволяет показывать ссылки на статьи сайта вместе с рекламой Яндекса. Проблема в том, что система от отечественного поисковика не очень умная и тянет в виджет не только статьи, но и много чего не нужного. Я написал микроплагин, который дает возможность автоматически проставлять специальный тег на страницах, которые не нужно показывать в виджете, а также позволяет исключать некоторые статьи из виджета вручную"
},
{
"title": "Сайт студии переводов «АкадемПеревод»",
"image": "/images/works/ap.jpg",
"year": 2022,
"category": "WordPress",
"link": "https://academperevod.ru/",
"description": "Осовременивали сайт, не перезжая с WordPress на другие платформы. В основе проекта - дизайн в Фигме и редактор Elementor. Сложная, долгая и кропотливая работа",
"scroll": true
}
]
I decided to filter the elements by category, which is specified by json.
Here is my component that displays a list of categories and adds filtering on the page above the list of all portfolio works:
//filter-work.js
import works from "@/content/works/data.json"
export default function FilterWork({selectedCat, onSelect}) {
const splitCats = works.flatMap((w) => w.category.split());
const categories = Array.from(new Set(splitCats));
return (
<div>
<ul>
<li
className={!selectedCat ? "bg-indigo-50 p-2 rounded-md" : "p-2"}
onClick={() => onSelect("")}
>
<a>Все</a>
</li>
{categories.map((category, i) => {
const isSelected = category === selectedCat
return (
<li key={i} item={category}
className={isSelected ? "bg-indigo-50 p-2 rounded-md" : "p-2"}
onClick={() => onSelect(category)}
>
{category}
</li>
)
})}
</ul>
</div>
)
}
And here is the code of the page that displays both a list of all the works and a list of categories in the filter. My main filter code is also here.
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";
export async function getStaticProps() {
const work = getAllWork();
return {
props: {
work,
},
};
}
export default function WorkPage({work}) {
const [selectedCat, setSelectedCat] = useState("");
const filteredCat = selectedCat ? work.filter((listItem) => listItem.category.includes(selectedCat))
: work;
return (
<div>
<Seo
title="Все работы Колтан Леонида"
description="Здесь собраны некоторые из работ разработчика Колтан Леонида"
ogImageUrl={`http://localhost:3000/api/og?title=Все работы Колтан Леонида&description=Здесь собраны некоторые из работ разработчика Колтан Леонида`}
/>
<section className='px-6'>
<div className='wrapper'>
<h1 className='sectionTitle'>Проекты</h1>
<FilterWork
selectedCat={selectedCat}
onSelect={setSelectedCat}
/>
<div className={styles.featuredWorkInner}>
{filteredCat.map((workItem) => (
<Work key={workItem.title} item={workItem} />
))}
</div>
</div>
</section>
</div>
)
}
The filter works, here it is on the test domain – https://next-site-ivory-six.vercel.app/work . The question is that I would like to add another filter by year, which is also specified in the json file. I tried to do something like this:
const filteredCat = selectedCat ? work.filter((listItem) => listItem.category.includes(selectedCat)) && work.filter((listItem) => listItem.year.toString().includes(selectedCat)): work;
But nothing works like that. It is filtered either by categories or by years depending on the operator that I will specify in the code above (&&
or ||
), and I need there to be mutual filtering – that is, if I chose WordPress
and 2022
, so that only works with the WordPress
category with the year 2022
are displayed. How to do it?
2
Answers
For multiple filters you need to define your filter function as follows
As per the comment below, either have selectedYear as number or use
==
in place of===
.Note that I am using
==
instead of using parseInt for year.