Trouble converting routes from react-router v3 to v4

745 views Asked by At

I have the following route configuration using react-router v3:

<Route component={App}>
  <Route path="login" component={Login} />
  <Route path="logout" component={Logout} />
  <Route path="/" component={Admin}>
    <IndexRoute component={Dashboard} />
    <Route path="profile" component={Profile} />
  </Route>
</Route>

I tried the following using v4:

<Router>
  <div id="app">
    <Match pattern="/login" component={Login} />
    <Match pattern="/logout" component={Logout} />
    <Match pattern="/" component={Admin} />
  </div>
</Router>

and inside Admin component:

<div id="admin">
  <Match pattern="/" component={Dashboard} />
  <Match pattern="/profile" component={Profile} />
</div>

The problem:

  1. When I visit /login, Admin component is also matched.
  2. I tried changing to <Match pattern="/" exactly component={Admin} />. It doesn't render the sub matches in the Admin component. So when I visit /profile, it has no match.
2

There are 2 answers

0
Paul S On

Nesting is still a bit wonky with v4, but it is still in alpha so that shouldn't be too unexpected.

As you have defined your code, there isn't a good way to do what you want. One possible solution would be to have a withAdmin higher order component that will render your admin HTML for wrapped components.

const withAdmin = (Component) => {
  return (matchProps) => (
    <div id="admin">
      <Component {...matchProps} />
    </div>
  )
}

Which you would use like:

<Router>
  <div id="app">
    <Match pattern="/login" component={Login} />
    <Match pattern="/logout" component={Logout} />
    <Match exactly pattern="/" component={withAdmin(Dashboard)} />
    <Match pattern="/profile" component={withAdmin(Profile)} />
  </div>
</Router>

It isn't ideal, but it should work.

There is also the possibility that the final version will include a <Match___> component which accepts an array of patterns and only renders the component associated with the first matched pattern. That would be a real solution to your problem, but it doesn't exist yet.

<Match___ routes={[
  { pattern: '/login', component: Login },
  { pattern: '/logout', component: Logout },
  { pattern: '/', component: Admin }
]} />
0
JDewitt On

I have been using the Switch module for nested Routes which has been working out okay for me so far:

<Router>
  <App>
    <Switch>
      <Route exactly pattern="/" component={Home} />
      <Route pattern="/about" component={About} />
      <Route pattern="/etc" component={Etc} />
    </Switch>
  </App>
</Router>

You can also use Switches inside of components for things like sub-navigation.