65

I'm trying to set up some nested routes to add a common layout. Check the code out:

  <Router>
    <Route component={Layout}>
      <div>
        <Route path='/abc' component={ABC} />
        <Route path='/xyz' component={XYZ} />
      </div>
    </Route>
  </Router>

While this works perfectly fine, I still get the warning:

Warning: You should not use <Route component> and <Route children> in the same route; will be ignored

Elias Zamaria
  • 80,938
  • 29
  • 103
  • 136
Sean Gillespie
  • 751
  • 1
  • 5
  • 6
  • 5
    Possible duplicate of [Nested routes with react router v4](http://stackoverflow.com/questions/41474134/nested-routes-with-react-router-v4) – Pio Apr 09 '17 at 07:32

5 Answers5

83

CESCO's answer renders first the component AppShell then one of the components inside Switch. But these components are NOT going to render inside AppShell, they will NOT be children of AppShell.

In v4 to wrap components you don't put anymore your Routes inside another Route, you put your Routes directly inside a component.
I.E : for the wrapper instead of <Route component={Layout}> you directly use <Layout>.

Full code :

  <Router>
    <Layout>
      <Route path='/abc' component={ABC} />
      <Route path='/xyz' component={XYZ} />
    </Layout>
  </Router>

The change is probably explained by the idea to make React Router v4 to be pure React so you only use React elements like with any other React element.

EDIT : I removed the Switch component as it's not useful here. See when it's useful here.

Ilan Schemoul
  • 1,254
  • 9
  • 15
  • Thanks! Wrapping it like: `` worked for me :) – protoEvangelion Mar 11 '17 at 21:28
  • 3
    No problem. If you use a single `Route` you do NOT need `Switch`. `Switch` is like the || operator : the first `Route` inside a `Switch` statement that match path is rendered but the other `Route`s inside the `Switch` are NOT rendered. I added a link to the doc of `Switch` in my comment. – Ilan Schemoul Mar 11 '17 at 22:33
  • 1
    Thanks, It's very useful. – slorenzo Apr 08 '17 at 19:31
  • Great solution. I – MLhacker Jun 02 '17 at 01:44
  • Thanks, this helped me to better understand and solve the problem. – Jaime Rios Oct 14 '17 at 13:55
  • what if you wanted another Route element which is NOT wrapped with layout? I'm struggling all day today to make it work and can't find proper way (example: ABC, XYZ are pages after you logged in, so they need Layout which contains sidebar, menu, etc, but you also need a Route for login page which doesn't need menus) – Kamil Mikolajczyk Oct 16 '17 at 21:46
  • 1
    How would one get a _location_ object or _location.pathname_ inside of Layout component (ie. `this.props.location.pathname`)? – Ibro Jan 08 '18 at 18:26
  • Why isn't this common knowledge! (Maybe it is now, but still had to search a fair amount to find it) - thank you, sir. – Jamie Jul 04 '18 at 14:11
10

You need to use the switch component to nesting to work nice. Also, see this question

// main app
<div>
    // not setting a path prop, makes this always render
    <Route component={AppShell}/>
    <Switch>
        <Route exact path="/" component={Login}/>
        <Route path="/dashboard" component={AsyncDashboard(userAgent)}/>
        <Route component={NoMatch}/>
    </Switch>
</div>

And version-4 components do not take children, instead, you should use the render prop.

<Router>
    <Route render={(props)=>{
      return <div>Whatever</div>}>
    </Route>
  </Router>
Vinit Raj
  • 1,670
  • 1
  • 12
  • 16
CESCO
  • 5,396
  • 4
  • 41
  • 73
5

Try:

<Router>
    <Layout>
        <Route path='/abc' component={ABC} />
        <Route path='/xyz' component={XYZ} />
    </Layout>
</Router>
marrekk
  • 69
  • 3
2

If you do not want Layout to run at loaded. Use this method:

<div className="container">
    <Route path="/main" component={ChatList}/>
    <Switch>
        <Route exact path="/" component={Start} />
        <Route path="/main/single" component={SingleChat} />
        <Route path="/main/group" component={GroupChat} />
        <Route path="/login" component={Login} />
    </Switch>
</div>

Whenever history changes, componentWillReceiveProps in the ChatList will run.

Avare Kodcu
  • 376
  • 4
  • 14
0

You can also try this :

<Route exact path="/Home"
                 render={props=>(
                                 <div>
                                      <Layout/>
                                      <Archive/>
                                </div>
                       )} 
    />