jerome
jerome

Reputation: 411

Sub pages not showing with React Router

I'm currently working on a site that offers expeditions, and one of the pages is supposed to have nested routes inside it eg: /expeditions/antarcticasouthgeorgia.

I've been following some of the other questions asked about this, and I can't seem to get my implementation to work.

My code and references are shown below. I appreciate the help. Thank you!

App.js

class App extends Component {
  render() {
    return (
      <div className="App">
        <Router>
          <ScrollToTop/>
          <NavMenu />
          <Switch>
            <Route exact path='/' component={Home}/>
            <Route exact path="/expeditions" component={Expeditions}/>
            <Route path="/expeditions/antarticasouthgeorgia" component={InnerExpeditions}/>
            <Route path="/about" component={About}/>
            <Route path="/contact" component={Contact}/>
          </Switch>
        </Router>
      </div>
    );
  }
}

export default App;

Expeditions.js

class Expeditions extends Component {
    render() {

        const OverviewThumbs = (props) => {
            return (
                props.data.map((item, index) => {
                    return (
                        <Col sm={6} lg={4}>
                            <Link to={item.url} className={`overview_thumbs overview_thumbs-${index}`} style={{ backgroundImage: `url(${item.image})` }}>
                                <div className="overview_header">
                                    {item.title}
                                </div>
                            </Link>
                        </Col>
                    )
                })
            )
        }

        const data = [
            {
                title: 'Antartica & South Georgia',
                image: contentImg1,
                url: '/antarticasouthgeorgia'
            },
        ]

        return (
            <div className="page-fade-in expeditions rootPadding">
                <Container fluid className="content overview px-0 pb-0" >
                    <Row className="g-0">
                        <Router basename="/expeditions">
                            <OverviewThumbs data={data} />
                        </Router>
                    </Row>
                </Container>
            </div>
        );
    }
}

export default Expeditions;

References

React how to create sub pages with react router to display?

React router - Navigate inner pages with sub route

https://www.youtube.com/watch?v=9z-X7UUid9Q

Upvotes: 2

Views: 1939

Answers (1)

Drew Reese
Drew Reese

Reputation: 202605

Issue

You are rendering more than one Router. The inner router is the closest routing context and will handle any navigation requests from its children. The outer router is rendering the routes. Since the inner router handles the navigation requests the outer router never knows to render different routes.

Solution

Check the official Route Nesting Demo

Remove the nested Router in Expeditions, you only need one router to handle the navigation in your app. You also don't want to declare an OverviewThumbs component in the render method as this will remount any time Expeditions rerenders. You can safely render that JSX in the rendered return.

Use the current match.url to append the next route segment to for the link.

class Expeditions extends Component {
  render() {
    const { url } = this.props.match;
    ...

    return (
      <div className="page-fade-in expeditions rootPadding">
        <Container fluid className="content overview px-0 pb-0" >
          <Row className="g-0">
            {props.data.map((item, index) => (
              <Col key={item.url} sm={6} lg={4}>
                <Link
                  to={`${url}/${item.url}`} // <-- link to nested route
                  className={`overview_thumbs overview_thumbs-${index}`} 
                  style={{ backgroundImage: `url(${item.image})` }}
                >
                  <div className="overview_header">
                    {item.title}
                  </div>
                </Link>
              </Col>
            ))}
          </Row>
        </Container>
      </div>
    );
  }
}

Also, with the Switch component, path order and specificity matter. You will want to order the paths in decreasing specificity. This allows path matching to work more naturally and you won't need to specify the exact prop on every route.

<Switch>
 <Route path="/expeditions/antarticasouthgeorgia" component={InnerExpeditions}/>
 <Route path="/expeditions" component={Expeditions}/>
 <Route path="/about" component={About}/>
 <Route path="/contact" component={Contact}/>
 <Route path='/' component={Home}/>

Upvotes: 1

Related Questions