user10746369
user10746369

Reputation:

react-router - Navigate to parent route from nested router

I'm playing around with react-router, and I have a problem when using nested routes.

Here is my parent router:

<Router>
    <div>
        <Route exact path="/" component={HomePage} />
        <Route path="/account" component={AccountDashboard} />
     </div>
 </Router>

Here is the router inside AccountDashboard:

<Router>
    <Route path="/account/password-reset" component={ChangePassword} />
    <Route path="/account/sign-out" component={SignOut} />
</Router>

Once I navigate to either /account/password-reset or /account/sign-out, I can't seem to navigate back to the root of the parent router (to view the HomePage component). The child router is just returning null.

For example, I tried calling both props.history.push('/') and props.history.reset('/') within the ChangePassword component, but the child router returns null.

If I add a route for '/' in the AccountDashboard router, any component I provide will render just fine because the router in AccountDashboard matches it, but I want to redirect to '/' within the ChangePassword component and show the HomePage component via the parent router.

How do I navigate to a route on a parent router within a child/nested router?

Edit: I just made a basic implementation from scratch, same problem:

import React, { Component } from 'react';
import './App.css';
import { BrowserRouter as Router, Route, Link, withRouter } from "react-router-dom";

const Blue = withRouter(({ history }) => (
  <div style={{ border: "1px solid #222", width: "300px", padding: "4px", margin: "4px"}}>
    <h2>Blue Component</h2>
    <span
      style={{color: 'blue', textDecoration: 'underline'}}
      onClick={() => { history.replace('/') }}>
      Go back to Letters
    </span>
  </div>
));

const Green = withRouter(({ history }) => (
  <div style={{ border: "1px solid #222", width: "300px", padding: "4px", margin: "4px"}}>
    <h2>Green Component</h2>
    <span
      style={{color: 'blue', textDecoration: 'underline'}}
      onClick={() => { history.replace('/') }}>
      Go back to Letters
    </span>
  </div>
));

const Letters = () => (
  <div style={{ border: "1px solid #222", width: "300px", padding: "4px", margin: "4px"}}>
    <h2>Letters (Root) Component</h2>
  </div>
)
const Colors = () => (
  <Router>
    <div>
    Child Router
    <br></br>
    [ <Link to="/colors/blue">Blue</Link> ]
    [ <Link to="/colors/green">Green</Link> ]
      <Route path="/colors/blue" exact component={Blue} />
      <Route path="/colors/green" component={Green} />
    </div>
  </Router>
);

class App extends Component {
  render() {
    return (
      <Router>
        <div>
        Parent Router
        <br></br>
        [ <Link to="/">Letters</Link> ][ <Link to="/colors">Colors</Link> ]
          <Route path="/" exact component={Letters} />
          <Route path="/colors" component={Colors} />
        </div>
      </Router>
    );
  }
}

export default App;

With the above code, the app will load and display the Letters component. If you click on Colors, you'll be taken to the second router, where you can select 'Blue' or 'Green', which each have a link back to '/'. When you follow that link, the URL changes correctly to '/', but the original Letters component does not display.

Upvotes: 3

Views: 8094

Answers (1)

Jim
Jim

Reputation: 658

@butchyyyy answered this for me in the comments but I'm answering in case someone else will find it.

he said: Is there any reason for using two Routers in your app? You should only have one router at the top level. Does this sandbox do what you want: codesandbox.io/s/8kwy5pkvm8

I have a main Navigation with a switch and one of the pages had a sub navigation.

What worked for me was to simply remove the second router component and use the parent path within child paths.

This is what the child component looks like:

const Apps = () => (
    <div className='main-container'>
    <SubNav items={subNavOptions} />
    <Route exact path='/apps' component={Applist} />
    <Route path='/apps/single-choice-lists' component={SingleChoiceLists} />
    <Route path='/apps/classification-sets' component={ClassificationSets} />
  </div>
)

Hope this helps someone else.

Upvotes: 5

Related Questions