React-router: Nested IndexRoute not working

Created on 15 Sep 2015  路  16Comments  路  Source: ReactTraining/react-router

I have this route setup, where I need nested IndexRoutes

<Route path="/admin" component={App}>
    <IndexRoute component={HomeBody}>
       <IndexRoute component={Overview}/>
    </IndexRoute>
    // more routes...
</Route>

But the inner IndexRoute doesn't ever seem to resolve.

Most helpful comment

@ryanflorence Sorry about writing to the closed issue.
You're saying that nesting IndexRoutes does not make sense, but why not?
What if I need complex default structure _without_ any redirects just at my root ('/' path)?
As long as new api provides component attributes to every route why do you not allow to nest default route component via children?

Like this: (Here App and Authorized components just render their children)

<Route path="/" component={App}>
    <IndexRoute component={Authorized}>
        <IndexRoute component={Feed}/>
    </IndexRoute>
    <Route path="login" component={Login}/>
</Route>

Another way to accomplish the desired behavior would be using just Route components without path specified and inheriting it from parent but that is not working.
Like this:

<Route path="/" component={App}>
    <Route component={Authorized}>
        <Route component={Feed}/>
    </Route>
    <Route path="login" component={Login}/>
</Route>

But actually this is just the same as using IndexRoute.

All 16 comments

That doesn't make sense, index routes are leaf nodes, can't be nested.

@ryanflorence Sorry about writing to the closed issue.
You're saying that nesting IndexRoutes does not make sense, but why not?
What if I need complex default structure _without_ any redirects just at my root ('/' path)?
As long as new api provides component attributes to every route why do you not allow to nest default route component via children?

Like this: (Here App and Authorized components just render their children)

<Route path="/" component={App}>
    <IndexRoute component={Authorized}>
        <IndexRoute component={Feed}/>
    </IndexRoute>
    <Route path="login" component={Login}/>
</Route>

Another way to accomplish the desired behavior would be using just Route components without path specified and inheriting it from parent but that is not working.
Like this:

<Route path="/" component={App}>
    <Route component={Authorized}>
        <Route component={Feed}/>
    </Route>
    <Route path="login" component={Login}/>
</Route>

But actually this is just the same as using IndexRoute.

<Route path="/" component={App}>
    <Route component={Authorized}>
        <IndexRoute component={Feed} />
    </Route>
    <Route path="login" component={Login}/>
</Route>

Does that make sense? We can follow up on Reactiflux or Stack Overflow - the issue tracker is not great for this sort of Q&A thing.

This seems like a valid issue. @taion's solution does not solve the problem.

Elaborate?

Maybe I am just confusing myself, but the discrepancies between the following cases are not intuitive:

This works:

<Route component={App}>
    <Route path="/ component={Authorized}>
        <IndexRoute component={Feed} />
        ...
    </Route>
    <Route path="/" component={LoginLayout}>
        <Route path="login" component={Login} />
        ...
    </Route>
</Route>

This _does not_ work:

<Route path="/" component={App}>
    <Route path="/" component={Authorized}>
        <IndexRoute component={Feed} />
        ...
    </Route>
    <Route path="/" component={LoginLayout}>
        <Route path="login" component={Login} />
        ...
    </Route>
</Route>

This also _does not_ work, but I think semantically captures what I am trying to do and should be supported:

<Route path="/" component={App}>
    <IndexRoute component={Authorized}>
        <IndexRoute component={Feed} />
        ...
    </Route>
    <Route path="/" component={LoginLayout}>
        <Route path="login" component={Login} />
        ...
    </Route>
</Route>

Should be

<Route path="/" component={App}>
    <Route component={Authorized}>
        <IndexRoute component={Feed} />
        ...
    </Route>
    <Route component={LoginLayout}>
        <Route path="login" component={Login} />
        ...
    </Route>
</Route>

Your second example doesn't work because it's trying to express // as a path to navigate to. Each path, even if duplicated, becomes a node in the route tree, separated by slashes (or being a slash itself if there is nothing else in the path).

You're really close. Here's what you need:

<Route path="/" component={App}>
    <Route component={Authorized}>
        <IndexRoute component={Feed} />
    </Route>
    <Route component={LoginLayout}>
        <Route path="login" component={Login} />
        <Route path="forgot_password" component={ForgotPassword} />
    </Route>
</Route>

Edit: What @taion said.

ah makes sense, thanks guys.

I believe I have found a case where nested routes for IndexRoute actually make sense. Please correct me if I am wrong.

I just commented over there.

@taion @ryanflorence Thank you both for clarification.

@timdorr I appreciate (and I'm using) the solution you gave. However it seems somewhat non-intuitive to me that a Route could fall through to an IndexRoute that is not an immediate child. It seems odd that the grandparent would be able to figure that one of its path-less children has an IndexRoute, so it should go ahead and fall through. Am I missing something conceptually about React Router?

It lets you handle cases like https://github.com/reactjs/react-router/issues/3326#issuecomment-210712055 cleanly.

@taion aha, interesting discussion. Thanks for sharing.

Yeah, so it's nothing conceptual and at some level it's a bit sloppy, but in practice it's really convenient for certain kinds of route definitions.

Was this page helpful?
0 / 5 - 0 ratings