I have a react application with react-router. I am trying to setup nested routes:
"/" --> home page
"/products" --> products list (child component of home page)
"/products/new" --> new product: child component of products list
What I tried to do so far:
<Route path="/" component="home" >
<Route path="products" component="products" >
<Route path="new" component="products_new" />
</Route>
</Route>
Now in the browser from my default home page, when I hit "/products"
, the products component is loaded and I can see my list of products. But when I hit "products/new"
nothing happens. I get a blank page. If I hit "/new"
(not nested) it works (page product_new is loaded inside its parent).
(this "/products/new"
does not work; this "/new"
works)
I had a look to this question on github Problem with nested routes #687. The solution says:
I discovered my problem. Parent routes are always called. Thats the intent. But child components need to have repeated
<Router.RouteHandler/>
to get rendered.
I cannot understand this solution. What does it mean:
"but child components need to have repeated
<Router.RouteHandler/>
to get rendered"
EDIT1: Here are my components (routers and views):
My routing hierarchy:
<Route path="/" >
<IndexRoute component={Home}/>
<Route path="products">
<IndexRoute component={Products} />
<Route path="new" component={Products_New} />
</Route>
</Route>
</Router>
My home component:
<div className="col-lg-12">
<h1>Home page</h1>
<hr />
{this.props.children}
</div>
My products components:
<div>
<div className="col-lg-12">
<h1>Products</h1>
</div>
<hr />
{this.props.children}
</div>
Have you had a look at IndexRoutes? If not, have a read about it on the official documentation. Your problem here is that when you visit /products/new
, react-router tries to render all components that are above your products_new
route.
This behavior is intended if you want to render a child component inside the parent component. Allow me to demonstrate with a couple of examples:
Consider the following home
component which has a Header and a Footer which is included on all pages.
<Header />
<div>{this.props.children}</div>
</Footer />
with the following routing:
<Route path="/" component={home} >
<Route path="products" component={products} />
</Route>
/
would render a page with just a <Header />
, an empty <div>
and <Footer />
./products
would render a page like above, but the <div>
would now contain your <Products />
component.Since, in your code you (probably) don't render {this.props.children}
you will always get the parent <Home />
component, regardless if you visited /
or /products
.
This behavior is useful for stuff that wrap the main elements of your site, such as menus, banners, sidebars, etc.
Now again consider the same home
component:
<Header />
<div>{this.props.children}</div>
</Footer />
but with this routing:
<Route path="/">
<IndexRoute component={home}
<Route path="products" component={products} />
</Route>
/
would render a page with just a <Header />
, an empty <div>
and <Footer />
./products
would now render your <Products />
component on its own, without being wrapped inside the parent <Home />
component.If you instead want each route to render individual components, and not everything under the tree of that route, you should use the following routing instead:
const browserHistory = useRouterHistory(createHistory)({basename: '/'});
ReactDOM.render(
<Route history={browserHistory}>
<Route path="/">
<IndexRoute component={home} />
<Route path="products" >
<IndexRoute component={products} />
<Route path="new" component={products_new} />
</Route>
</Route>
</Router>,
document.getElementById('content')
);