Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Trying to apply a filter to categories inside a nested array full of objects

I have 6 articles and would like to know how can I filter the articles based on the article category. Currently, I have this nested categories array inside the articles array.

Now I have some static buttons for the categories, but onClick I need them to filter the existing array of articles.

import { NextPage } from "next";
import Head from "next/head";

import PreFooterModule from "@modules/PreFooterModule";

import Footer from "@components/Footer";
import ArticlesHero from "@components/ArticlesHero";
import Link from "next/link";
import { useState } from "react";

const Articles: NextPage = () => {
  const [articles, setArticles] = useState([
    {
      image: "https://picsum.photos/1280/720?=1",
      title: "Article #1",
      text: "Here are the biggest enterprise technology acquisitions of 2021 so far, in reverse chronological order.",
      categories: ["Fashion", "Products"],
    },
    {
      image: "https://picsum.photos/1280/720?=2",
      title: "Article #2",
      text: "Here are the biggest enterprise technology acquisitions of 2021 so far, in reverse chronological order.",
      categories: ["Fashion", "Travel"],
    },
    {
      image: "https://picsum.photos/1280/720?=3",
      title: "Article #3",
      text: "Here are the biggest enterprise technology acquisitions of 2021 so far, in reverse chronological order.",
      categories: ["Movies", "Studio"],
    },
    {
      image: "https://picsum.photos/1280/720?=4",
      title: "Article #4",
      text: "Here are the biggest enterprise technology acquisitions of 2021 so far, in reverse chronological order.",
      categories: ["Fashion", "Products"],
    },
    {
      image: "https://picsum.photos/1280/720?=5",
      title: "Article #5",
      text: "Here are the biggest enterprise technology acquisitions of 2021 so far, in reverse chronological order.",
      categories: ["Television", "Movies"],
    },
    {
      image: "https://picsum.photos/1280/720?=6",
      title: "Article #6",
      text: "Here are the biggest enterprise technology acquisitions of 2021 so far, in reverse chronological order.",
      categories: ["Studio", "Fashion"],
    },
  ]);

  return (
    <>
      <Head>
        <title>Artikel Overzicht</title>
        <meta name="author" content="" />
        <meta name="description" content="" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <ArticlesHero
        title="Artikel Overzicht"
        text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
      />

      <div className="max-w-screen-xl px-6 pt-16 pb-12 mx-auto lg:px-8 text-navyBlue">
        <div className="flex gap-2 py-7">
          <a href="#" className="badge badge-primary">
            Fashion
          </a>
          <a href="#" className="badge badge-primary">
            Studio
          </a>
          <a href="#" className="badge badge-primary">
            Movies
          </a>
          <a href="#" className="badge badge-primary">
            Products
          </a>
          <a href="#" className="badge badge-primary">
            Travel
          </a>
          <a href="#" className="badge badge-primary">
            Television
          </a>
        </div>

        <div className="grid grid-cols-1 gap-y-10 gap-x-4 md:grid-cols-12">
          {articles.map(({ image, title, text, categories }) => (
            <article className="col-span-6 lg:col-span-4">
              <img
                className="object-cover rounded-md aspect-video"
                src={image}
                alt=""
              />
              <div className="pt-4">
                <div className="card-actions">
                  {categories.map((category) => (
                    <Link href="/tag/fashion" passHref>
                      <span className="text-[11px] font-semibold uppercase cursor-pointer badge badge-outline hover:bg-navyBlue hover:text-white">
                        {category}
                      </span>
                    </Link>
                  ))}
                </div>
              </div>
              <div className="py-3">
                <h5 className="mb-2 text-2xl font-medium tracking-tight text-navyBlue md:text-3xl">
                  {title}
                </h5>
                <p className="text-sm leading-snug text-black md:text-normal">
                  {text}
                </p>
                <Link href="/article/first-article" passHref>
                  <span className="inline-flex items-center justify-center px-4 py-1.5 md:py-2 text-xs font-medium uppercase transition duration-150 ease-in-out bg-transparent border rounded-full shadow-sm cursor-pointer mt-5 text-navyBlue border-navyBlue place-self-start  hover:border-transparent hover:bg-navyBlue hover:text-white">
                    Read more
                    <svg
                      className="w-4 h-4 ml-2 -mr-1"
                      fill="currentColor"
                      viewBox="0 0 20 20"
                      xmlns="http://www.w3.org/2000/svg"
                    >
                      <path
                        fillRule="evenodd"
                        d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z"
                        clipRule="evenodd"
                      ></path>
                    </svg>
                  </span>
                </Link>
              </div>
            </article>
          ))}
        </div>
      </div>

      <PreFooterModule />
      <Footer />
    </>
  );
};

export default Articles;

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

First you need to clone the state. There need to be a copy of the articles. So that if we filter and set the state we won’t lose other articles. So do something like,

const [articlesCopy, setArticlesCopy] = useState(articles)

Then, on clicking each buttons you should fire a function with the category as parameter. And this function is responsible of filtering the data present in articlesCopy and sets in articles state.

So create a function like,

const filterByCategory = (category) => {
    const filteredArticles = articles.filter(article => article.categories.includes(category); // Filter based on category

    setArticles(filteredArticles); // Set the actual state, so it re-renders
}

And in your button do something like,

<a onClick={()=>filterByCategory("Fashion")} className="badge badge-primary">
        Fashion
</a>

<a onClick={()=>filterByCategory("Movies")} className="badge badge-primary">
        Movies
</a>
....

First you need to clone the state. There need to be a copy of the articles. So that if we filter and set the state we won’t lose other articles. So do something like,

const [articlesCopy, setArticlesCopy] = useState(articles)

Then, on clicking each buttons you should fire a function with the category as parameter. And this function is responsible of filtering the data present in articlesCopy and sets in articles state.

So create a function like,

const filterByCategory = (category) => {
    const filteredArticles = articles.filter(article => article.categories.includes(category); // Filter based on category

    setArticles(filteredArticles); // Set the actual state, so it re-renders
}

And in your button do something like,

<a onClick={()=>filterByCategory("Fashion")} className="badge badge-primary">
        Fashion
</a>

<a onClick={()=>filterByCategory("Movies")} className="badge badge-primary">
        Movies
</a>
....

To render those buttons dynamically you can do something like,

let categories = [];
articles.forEach(article => {
    categories.push(article.categories);
});
categories = Array.from(new Set(categories));

setCategories(categories);

And use this new categories state to render those buttons

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading