Home > other >  React Router DOM - Using only one param in URL Structure
React Router DOM - Using only one param in URL Structure

Time:01-23

I have an e-commerce app, where I am trying to structure the URL so that it only takes one parameter -

<Route path={process.env.PUBLIC_URL   "/:value"} component={ShopProducts} />

This value could either be a category like "suits" or a sub-category like "blazers", "pants", etc.

In my current structure, my Route looks like this:

<Route path={process.env.PUBLIC_URL   "/:category/:sub-category"} component={ShopProducts} />

And in my ShopProducts component, I send those two URL Params as one keyword to filter the products. For Example, if the path is "/suits/blazers", in the component, they become a query string ?category="suits"&sub-category="blazers" and thus, it sends a GET request, filtering the products at the endpoint using the query.

Now, my problem is if I make the Route only take one param, that is, the sub-category, I will not have the category param to make the query string. For Example, if the path is "/blazers", the query string becomes: ?category=&sub-category="blazers" and thus, the filtering doesn't work.

This is how the data in my endpoint looks like:

{
"id": 1,
"name": "Suits",
"slug": "suits",
"parent": null,
"sub_category": [
    {
        "id": 5,
        "name": "Blazers",
        "slug": "blazers",
        "parent": 1,
    },
    {
        "id": 6,
        "name": "Pants",
        "slug": "pants",
        "parent": 1,
    },
]

I have tried making this happen by using an onClick function that saves the parent category in Redux and then filters using the sub-category, however, that solution is not scalable and if someone tries to access the URL directly (without onClick), it doesn't work.

How do I change the Route to only take one value, that is, the sub-category and access the category through it?

CodePudding user response:

You can take the sub-category parameter and search the data for the parent and retrieve the main category.

const getCategory = (data, subCategory) =>
  data.find((category) =>
    category.sub_category.some(
      (subCat) => subCat.slug.toLowerCase() === subCategory.toLowerCase()
    )
  )?.slug;

const data = [
  {
    id: 1,
    name: "Suits",
    slug: "suits",
    parent: null,
    sub_category: [
      {
        id: 5,
        name: "Blazers",
        slug: "blazers",
        parent: 1
      },
      {
        id: 6,
        name: "Pants",
        slug: "pants",
        parent: 1
      }
    ]
  },
  {
    id: 2,
    name: "Costumes",
    slug: "costumes",
    parent: null,
    sub_category: [
      {
        id: 3,
        name: "Clown",
        slug: "clown",
        parent: 2
      },
      {
        id: 4,
        name: "Police",
        slug: "police",
        parent: 2
      }
    ]
  }
];

const getCategory = (data, subCategory) =>
  data.find((category) =>
    category.sub_category.some(
      (subCat) => subCat.slug.toLowerCase() === subCategory.toLowerCase()
    )
  )?.slug;

console.log("blazers", getCategory(data, "blazers")); // blazers suits
console.log("pants", getCategory(data, "pants")); // pants suits
console.log("shoes", getCategory(data, "shoes")); // shoes undefined
console.log("police", getCategory(data, "police")); // police costumes
console.log("clown", getCategory(data, "clown")); // clown costumes

Now for a given route

<Route path={`${process.env.PUBLIC_URL}/:subCategory`} component={ShopProducts} />

the ShopProducts component reads the subCategory route path parameter and computes the main category.

const ShopProducts = () => {
  const { subCategory } = useParams();
  const category = getCategory(data, subCategory);

  ...
};
  • Related