I’m using react-router-dom 5.2.0
App.jsx
`<Route path="/shop">
<ProductListPage />
</Route>
<Route path="/shop/:page">
<ProductListPage />
</Route>
<Route path="/shop/:gender/:category?">
<ProductListPage />
</Route>
<Route path="/shop/:filter">
<ProductListPage />
</Route>`
ProductListPage.jsx
`import { useParams } from "react-router-dom";
export default function ProductListPage() {
let { page } = useParams();
let { gender, category } = useParams();
let { filter } = useParams();
console.log(page + " " + gender + " " + filter + " " + category);
return (
<div className="bg-light-gray-1">
<ProductCategories />
<ProductList />
<ClientList />
</div>
);
}`
Can’t get page or gender or anything, just undefined.
I have one page for listing all products.
Second one is for pagination
Third one is for categorization
And fourth one is for filtering
But variables where i get from links is not working. For example;
"/shop/women/tshirt" "/shop/man/shoe" "/shop/1
I’ve tried to get values like this but keep getting undefined values.
`import { useParams } from "react-router-dom";
export default function ProductListPage() {
let { page } = useParams();
let { gender, category } = useParams();
let { filter } = useParams();
console.log(page + " " + gender + " " + filter + " " + category);
In React-Router-DOM v5 the route order and path specificity matters. The routes are matched from the top-down in the order they are specified, and path="/shop"
matches all path="/shop/*"
routes as well, so it is the route that get rendered and renders the ProductsListPage
component and no path parameters are set. This is why page
, gender
, and category
are all undefined.
Re-order the routes such that the more specific routes can be matched first before falling back to less specific routes.
Note also that path="/shop/:page"
and path="/shop/:filter"
the same specificity, so only one or the other can be matched ever, whichever is listed first. This is effectively a duplicate route and one should be removed.
Example:
<Switch>
...
<Route path="/shop/:gender/:category?">
<ProductListPage />
</Route>
<Route path="/shop/:page">
<ProductListPage />
</Route>
<Route path="/shop">
<ProductListPage />
</Route>
...
</Switch>
or
<Switch>
...
<Route path="/shop/:gender/:category?" component={ProductListPage} />
<Route path="/shop/:page" component={ProductListPage} />
<Route path="/shop" component={ProductListPage} />
...
</Switch>
React-Router-DOM 5 Route
components can also take an array of paths, so instead of duplicating the routes that all render the same ProductListPage
component you can declare a single route and pass the paths in an array. The path order still matters here as well.
<Switch>
...
<Route
path={[
"/shop/:gender/:category?",
"/shop/:page",
"/shop"
]}
>
<ProductListPage />
</Route>
...
</Switch>
or
<Switch>
...
<Route
path={[
"/shop/:gender/:category?",
"/shop/:page",
"/shop"
]}
component={ProductListPage}
/>
...
</Switch>
In ProductListPage
you only need a single useParams
hook call, all the params can be destructured from the returned params
object.
import { useParams } from "react-router-dom";
export default function ProductListPage() {
const { page, gender, category } = useParams();
console.log({ page, gender, category });
...
}
Rearrange your App.jsx
routes
<Route path="/shop/:gender/:category?">
<ProductListPage />
</Route>
<Route path="/shop/:page">
<ProductListPage />
</Route>
<Route path="/shop/:filter">
<ProductListPage />
</Route>
<Route path="/shop">
<ProductListPage />
</Route>