Reputation: 473
In v5, we could add trailing ?
to route for optional parameters, but as in v6, the support for the same has been dropped, so what's the alternate way of writing the following piece of code?
<Route path="/cart/:id?" component={<CartPage />} />
Upvotes: 47
Views: 36129
Reputation: 202721
[email protected]+
Optional segments/parameters have been re-introduced to the library. The docs have been updated, but v6.5.0 Release Notes include the details as well.
The above routes can be merged to a single route:
<Route path="/cart/:id?" element={<CartPage />} />
[email protected]
After quite a bit of digging through the source code to understand how path parsing was different in RRDv6 from RRDv5, and turned up nothing really other than they no longer use path-to-regex
, I hit up the repo's issues section and found this issue which outright states they don't plan to support optional path parameters in v6.
See FAQ: What Happened to Regexp Routes Paths?
It seems the suggested solution is to render 2 routes to match either path and render the same component.
Example:
<Route path="/cart/:id" element={<CartPage />} />
<Route path="/cart/" element={<CartPage />} />
or
<Route path="/cart">
<Route index element={<CartPage />} />
<Route path=":id" element={<CartPage />} />
</Route>
The latter is really only syntactic sugar around relative paths from "/cart" though.
Upvotes: 70
Reputation: 1
import * as React from 'react';
import {useNavigate} from "react-router-dom"
function App() {
const location = useNavigate();
React.useEffect(() => {
ga('send', 'pageview');
location("/route");
}, [location]);
return (
// ...
);
}
this is not working because it is not supported in version 6 in react router dom you must use import {useNavigate} from "react-router-dom"
Upvotes: 0
Reputation: 31
It would be great if this could be described in the migration guide – or if there was at least a hint. So the recommended way of doing "optional" params really is ...
<Route path='/page/:friendlyName/:sort' element={<Page/>} />
<Route path='/page/:friendlyName/' element={<Page/>} />
Upvotes: 3
Reputation: 5778
Base react router doc
https://reactrouter.com/docs/en/v6/hooks/use-location
would not this work?
import * as React from 'react';
import { useLocation } from 'react-router-dom';
function App() {
let location = useLocation();
React.useEffect(() => {
ga('send', 'pageview');
}, [location]);
return (
// ...
);
}
Upvotes: 0
Reputation: 4064
Use wildcard:
<Route path="/cart/*" component={<CartPage />} />
Upvotes: 5
Reputation: 2986
As Drew Reese said, there is no support for the optional parameters in v6 (at least as of now).
I have ended up writing these little helper functions that register all nested routes for the optional parameters.
const registerOptionalParamRoute = (optionalParams: string[], element: Element) => {
if (optionalParams.length === 0)
return <Fragment/>;
const param = optionalParams[0];
optionalParams.splice(0, 1);
return <Route path={param} element={element}>
{registerOptionalParamRoute(optionalParams, element)}
</Route>;
};
const registerOptionalParams = (path: string, element: JSX.Element) => {
const params = path.split("/");
let basePath = "";
let optionalParams = [];
for (let i = 0; i < params.length; i++) {
if (params[i] === '')
continue;
if (!params[i].includes("?"))
basePath += "/" + params[i];
else
optionalParams.push(params[i].substr(0, params[i].length - 1));
}
return <Route path={basePath} key={basePath} element={element}>
{registerOptionalParamRoute(optionalParams, element)}
</Route>;
};
Then call it:
<Routes>
{registerOptionalParams('/component/:param1?/:param2?', <Component/>)}
</Routes>
For an example url /component/:param1?/:param2?
and given component <Component/>
it generates the following jsx element:
<Route path="component" element={<Component/>}>
<Route path=":param1" element={<Component/>}>
<Route path=":param2" element={<Component/>} />
</Route>
</Route>
I have also created feature request for optional parameters (https://github.com/remix-run/react-router/issues/8381), will see what feedback it will get.
Upvotes: 7