I have 3 possible paths that can be under one path. Is there any method that I can match all possible matches?
For example, the code as-is like
const MyComponent = () => {
const firstMatch = useMatch('/:appId/:firstKey');
const secondMatch = useMatch('/:appId/:firstKey/:secondKey');
const thirdMatch = useMatch('/:appId/:firstKey/:secondKey/:thirdKey');
if (firstMatch == null && secondMatch == null && thirdMatch == null) {
return <Navigate to="/" replace={true} />;
}
const firstKey =
(firstMatch?.params.firstKey) ||
(secondMatch?.params.firstKey) ||
(thirdMatch?.params.firstKey);
return ....
pseudo-code should be..
const firstMatch = useMatch('/:appId/:firstKey?/:secondKey?/:thirdKey');
But I found that the question mark pattern is removed as of version 6.
Do I have better option?
Optional path params are available for the Route
component's path
prop, but for the time being they are incompatible with the useMatch
hook and matchPath
utility function. There is a filed github issue & discussion regarding processing optional path segments in these hooks and utilities.
If you are looking for something a little more DRY than using three separate useMatch
hooks then I'd recommend loading the paths you want to match into an array and iterating over each, checking the path with the matchPath
utility function.
The logic may look similar to the following:
const patterns = [
"/:appId/:firstKey/:secondKey/:thirdKey",
"/:appId/:firstKey/:secondKey",
"/:appId/:firstKey"
];
const MyComponent = () => {
const { pathname } = useLocation();
const match = patterns.reduce(
(match, pattern) => (match ? match : matchPath(pattern, pathname)),
null
);
if (!match) {
return <Navigate to="/" replace />;
}
const { firstKey } = match.params;
return (
....
);
};
Since optional path segments work, it might just be easier to only match the routes you want to begin with.
Example:
const MyComponent = () => {
const { firstKey } = useParams();
return (
...
);
};
<Routes>
....
<Route
path="/:appId/:firstKey/:secondKey?/:thirdKey?" // <-- firstKey required
element={<MyComponent />}
/>
....
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>