8

I would like to add a log in page that doesn't have App as a parent. This is my current HashRouter setup:

  <Provider store={ store }>
    <HashRouter>
      <App>
        <Route path='/path1' component={ Component1 } />
        <Route path='/path2' component={ Component2 } />
        <Route path='/path3' component={ Component3 } />
      </App>
    </HashRouter>
  </Provider>

If I do this:

  <Provider store={ store }>
    <HashRouter>
      <div>
        <Route path='/login' component={ Login } />
        <App>
          <Route path='/path1' component={ Component1 } />
          <Route path='/path2' component={ Component2 } />
          <Route path='/path3' component={ Component3 } />
        </App>
      </div>
    </HashRouter>
  </Provider>

Then I get the login page above the App. Here's my App Component:

const App = ({ children }) => (
  <div>
    <Navbar/>
    <div className='col-md-10 col-md-offset-1'>
      { children }
    </div>
  </div>
)

What's the best way to get a login path with a Login component, that doesn't include the App?

Wylliam Judd
  • 9,935
  • 2
  • 26
  • 36
  • Why don't you add a subpath for `App`? e.g. `/session`. You could also just use `App` in every component instead of using it as a parent. There is no "best way". There are many many solutions. – Sulthan Apr 17 '17 at 20:17
  • I wouldn't want `/session` in the url of every page, that would be aesthetically unpleasing. – Wylliam Judd Apr 19 '17 at 15:15

2 Answers2

6

Since you are using react-router v4, you need to put your nested routes inside the parent component instead of nesting routes. See this answer for the explanation.

In your case, the simplest approach would be something like this.

<Provider store={ store }>
  <HashRouter>
    <div>
      <Switch>
        <Route path='/login' component={ Login } />
        <Route path='/' component={ App } />
      </Switch>
    </div>
  </HashRouter>
</Provider>

const App = () => (
  <div>
    <Navbar/>
    <div className='col-md-10 col-md-offset-1'>
      <Route path='/path1' component={ Component1 } />
      <Route path='/path2' component={ Component2 } />
      <Route path='/path3' component={ Component3 } />
    </div>
  </div>
)

Notice that how I have used <Switch> to wrap the '/login' and '/' routes. This will make sure that it only renders the first matching route from the given routes according to given order. So when the path is '/login', it will only render Login page even though it also matches(not exact match, you need to use 'exact' attribute for an exact match) the '/' route.

Update:

Above method is the recommended approach in react-router documentation. But if you see a value in keeping all your routes in one place, you can still use <Switch> with what you already have.

<Provider store={ store }>
  <HashRouter>
    <div>
      <Switch>
        <Route path='/login' component={ Login } />
        <App>
          <Route path='/path1' component={ Component1 } />
          <Route path='/path2' component={ Component2 } />
          <Route path='/path3' component={ Component3 } />
        </App>
      </Switch>
    </div>
  </HashRouter>
</Provider>
Community
  • 1
  • 1
Tharaka Wijebandara
  • 7,955
  • 1
  • 28
  • 49
  • I knew about `exact path` but not ``. Thank you for this answer. I do think there are merits to having a big Router with all your routes in it - it serves to show you what all your routes are. If I wanted to nest my other paths inside my `` how would I do that? – Wylliam Judd Apr 19 '17 at 15:18
1

You can use different layouts with a very basic main layout.

routes.js

export default () => (
    <Route path="/" component={Layout}>
        <Route component={WebLayout}>
            <IndexRoute component={Home} />
        </Route>
        <Route component={AppLayout}>
            <Route path="account" component={Account} />
        </Route>
        <Route component={SecurityLayout}>
            <Route path="login" component={Login} />
        </Route>
    </Route>
);

layout.js

const Layout = ({ children }) => (
    <div>
        {children}
    </div>
);

applayout.js

const AppLayout = ({ children }) => (
    ...
);

securitylayout.js

const SecurityLayout = ({ children }) => (
    ...
);
Austin Winstanley
  • 1,339
  • 9
  • 19