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);
...
};