RHok
RHok

Reputation: 152

React router v4 routes setup

During the migration from v2 to v4, my routes are now set up like so:

ReactDOM.render(
<Provider store={store}>
    <Router>
        <Route path='/admin' component={App} />
    </Router>
</Provider>
, document.getElementById('root'))

with the app component being

class App extends Component {

  render() {
    return (
      <AppContainer>
        <Switch>
          <Route path="/admin/dashboard" component={Dashboard} />
          <Route path="/admin/signin" component={SignIn} />
          <Route path="/admin/settings" component={Settings} />
        </Switch>
      </AppContainer>
    );
  }
}

In the app container, it calls an action which checks the login and then router.history.push('/admin/dashboard') if the login is valid. The rest of the AppContainer component is

render() {
    return (
        <div>
          {this.props.children}
          <Detached />
        </div>
    )
  }

Going to /admin sends you to /admin/dashboard correctly. Going to /admin/dashboard 404's, seemingly not even matching the first route path "/admin".

Am I doing anything blatantly wrong? Shouldn't going to /admin/xxxxx be matched by the first route?

Upvotes: 0

Views: 260

Answers (1)

JustinTRoss
JustinTRoss

Reputation: 787

It would be helpful to know where your 404 route is and whether there is any logic governing the push to '/admin/dashboard.

'/admin/xxxxx' should definitely result in a match for '/admin' as long as there is no 'strict' or 'exact' prop.

Potential error: If the logic in AppContainer checks login status and performs push to '/admin/dashboard' regardless of current pathname, then your app may be falling into the below recursive cycle:

  1. User navigates to '/admin'
  2. Route checks pathname '/admin' against path prop '/admin' and finds a match
  3. Route renders 'App' component
  4. AppContainer verifies that user is logged in
  5. AppContainer pushes user to '/admin/dashboard'
  6. Application rerenders with pathname '/admin/dashboard'
  7. Route checks pathname '/admin/dashboard' against path prop '/admin' and finds a match
  8. Route renders App component
  9. AppContainer verifies that user is logged in
  10. AppContainer pushes user to '/admin/dashboard'
  11. Application rerenders with pathname '/admin/dashboard'
  12. ...

The simplest fix to implement would be to only push to '/admin/dashboard' if pathname is '/admin'.

A fix with arguably less cognitive overhead would be to remove the manual history.push to '/admin/dashboard' and change App to the following:

class App extends Component {

    render() {
        return (
            <AppContainer>
                <Switch>
                    <Route exact path="/admin" render={() => <Redirect to='/admin/dashboard' />} />
                    <Route path="/admin/dashboard" component={Dashboard} />
                    <Route path="/admin/signin" component={SignIn} />
                    <Route path="/admin/settings" component={Settings} />
                </Switch>
            </AppContainer>
        );
    }
}

Upvotes: 1

Related Questions