Delegate route matching logic from <Switch> to <Route> (feature request)
See original GitHub issueHello,
currently you have following logic in <Switch> component:
<Switch> component makes assumption, that it will always receive the ‘whatever’ component, but with the specific options (path, exact, etc).
What the bad here is that if you’ll want to wrap <Route> component in HOC with a different props interface, this new <HocRoute> won’t work with <Switch> anymore, because <Switch> has its own copy-pasted matching logic and it, actually routes and only then switches.
What I want to propose is to delegate routing logic to <Route> components only. E.g. by creating static computeMatch() method and by calling element.type.computeMatch(props, router) instead of calling matchPath() on props, that do not belong to <Switch> component.
I know, that element.type is a little bit hacky, but this will allow a great composability and extendability of react-router.
The use cases
Named routes
You can implement something like this:
<NamedRoute name="home" component={HomePage} />
import { Route } from 'react-router-dom';
const routes = {
home: '/'
};
class NamedRoute extends Component // or it can be extends Route too {
static computeMatch({ name, ...rest }, router) {
const path = routes[name] || '/';
return Route.computeMatch({ path, ...rest }, router);
}
render() {
return <Route {...this.props} />;
}
}
Route aliasing
<Route aliases={['/', '/index']} component={HomePage} />
import { Route, Switch } from 'react-router-dom';
class AliasRoute extends Component {
static computeMatch({ aliases, ...rest }, router) {
// btw. the alias can be the whole object
// with props for Route instead of only path
return aliases.reduce((match, path) => {
if (match) {
return match;
}
return Route.computeMatch({ path, ...rest }, router);
}, null);
}
render() {
const { aliases, ...rest } = this.props;
return (
<Switch>
{aliases.map((path) => (
<Route path={path} {...rest} />
))}
</Switch>
);
}
}
This component can actually solve another <Switch> nesting problem, but the actual <Switch> component is hidden inside <AliasRoute>.
Switch nesting
The <Switch> can actually implement computeMatch() too and allow nesting:
static computeMatch({ children, location }, router) {
let match = null;
React.Children.forEach(children, (child) => {
if (match) {
return true;
}
match = child.type.computeMatch({location, ...child.props}, router);
});
return match;
}
Issue Analytics
- State:
- Created 6 years ago
- Reactions:14
- Comments:8 (1 by maintainers)

Top Related StackOverflow Question
I’m currently having problems with the same issue (having my own route component and not being able to say “don’t use this route”). Having a
SwitchableComponent#computeMatchoverride check looks best to me, due to its ability to look at the props of the component viathis.props.My use case is routes that are only available when a user has certain permissions. This is currently “not easy” to “very difficult” to specify with just components.
I’m not sure I’m sold on this. Re-using a property of the component seems like a good idea, but it means we are depending on the type of child given to Switch. The dirty little secret of Switch right now is that this works:
We basically fail gracefully if you pass a “bad” child in.
I’m also pessimistic about a hidden API surface. This should be more out in the open. Perhaps <Switch> could use a
computeMatchprop that takes a function for computing the match. That is more explicit and visible.