1

I'd like to define the following structure on my page:

enter image description here

Where layout is static and contains elements that appear on every page, and render page content based on the URL.

To achieve this I've defined AppRoutes, Layout, About and NotFound and used react-router, v4:

AppRoutes.js

export default class AppRoutes extends React.Component
{  
    render ()
    {
        const supportsHistory = 'pushState' in window.history;
        return (
        <BrowserRouter forceRefresh={!supportsHistory} history={hashHistory} onUpdate={() => window.scrollTo(0, 0)}>
            <div>
                <Route path='/' component={Layout}>
                    <Route path='/about' component={About}/>
                    <Route path='*' component={PageNotFround}/>
                </Route>
            </div>
        </BrowserRouter>);
    };
};

Layout.js

class NaviGationPane extends React.Component
{
    render()
    {
        return (
            <div>
                <NavLink to="/">Home</NavLink>
                <NavLink to="/about">About</NavLink>
            </div>
        )
    }
}

export default class Layout extends React.Component
{
    render ()
    {
        return (
        <div className="app-container">
            <header>
                <NaviGationPane/>
            </header>
            <div className="app-content">
                {this.props.children}
            </div>
        </div>
        );
    }
}

Layout's header is rendered, but at / or at /about the page content is empty. If I change it to the one below the PageNotFound is rendered always at the end, no matter what is the path, while the rest works as I expected, namely / renders he Layout, while /about renders the About component.

<BrowserRouter forceRefresh={!supportsHistory} history={hashHistory} onUpdate={() => window.scrollTo(0, 0)}>
                <div>
                    <Route path='/' component={Layout}/>
                    <Route path='/about' component={About}/>
                    <Route path='*' component={PageNotFround}/>
                </div>
            </BrowserRouter>

I checked that in both cases this.props.children in Layout is undefined.

UPDATE I tried out a few things and figured that

 <Layout>
     <Switch>
         <Route exact path='/' component={IndexPage}/>
         <Route path='/about' component={About}/>
         <Route component={PageNotFround}/>
      </Switch>
 </Layout>

will be the basic scenario and now I understand why my previous code did not work: in react-router v4 the

<Route to='/' component={Layout}>
       <Route path='/about' component={About}/>
</Route>

is not valid. The structure

<BrowserRouter>
      <div>
         <Route path='/' component={Layout}>
         <Route path='/about' component={About}/>
         <Route path='*' component={PageNotFround}/>
      </div>
 </BrowserRouter> 

will keep matching routes until all rules are exhausted, the / will be matched every time and * will also be matched every time.

So I use the <Layout> component to wrap everything and create the routes inside and to ensure that only one path is matched I use the <Switch>.

This is not what I wanted, because if I add a path /about/:user only the About component will be rendered. So the question is still open.

Pio
  • 4,044
  • 11
  • 46
  • 81
  • the code looks good, I think it can be a problem connected with version 4. Look at this topic: https://github.com/ReactTraining/react-router/issues/3928 – niba Apr 07 '17 at 08:27
  • I got some useful information from it but it is not really the answer, as my update says. – Pio Apr 08 '17 at 04:29
  • ```...``` – Rei Dien Apr 08 '17 at 11:28
  • @ReiDien, this is exactly what I wrote under the **UPDATE** part. My question is how to add routes `/about` and `/about/:user` as a single entry in the switch – Pio Apr 09 '17 at 01:25
  • 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:34
  • I found the explanation at https://egghead.io/lessons/react-render-nested-routes-with-react-router-v4. In short routes can be nested in components – Pio Apr 09 '17 at 07:59

0 Answers0