简体   繁体   中英

React-router nested routes with history.push

I have a react page that renders either a login page or navbar + container component based on the current route. I do not want the navbar to be visible with login page. My app is thus structured as follows:

index.js

ReactDOM.render(<Main/>, document.getElementById('root'));

Main.js

<Router>
  <Switch>
    <Route path="/login" component={Login} />
    <PrivateRoute path="/" component={App} />
  </Switch>
</Router>

App.js

<Router>
  <div className="App">
    <Navbar/>
    <div className="main-container">
      <Switch>
        <Route exact path="/" component={Container1}/>
        <Route path="/route1" component={Container2}/>
        <Route path="/route2" component={Container3}/>
      </Switch>
    </div>
  </div>
</Router>

Now if in inside any of the Container components I want to do a this.props.history.push('/login') it only affects the closest < Switch > and thus not rendering anything in the container area (since no routes match) but keeping the navbar visible. How could I get the parent < Switch > from Main.js to decide what to render on programmatic route change? Should I structure the app in some other way?

Thanks.

The trick was to remove the excess < Router > in App.js and export it with withRouter(App) at the end of the file. Thanks Nenad Vracar

You could define different sets of routes. Default routes that will display your navbar at all times, and other routes that wont.

class App extends React.Component{
    render(){
        const DefaultRoutes = () => {
            return(
                <div>
                    <Navbar/>
                    <Switch>
                        <Route path="/" component={Landing} exact={true}/>          
                    </Switch>                                                                                                           
                    <Footer/>
                </div>
            )
        }

        return(
            <Provider store={store}>
                <BrowserRouter>
                    <div className="App">
                        <Switch>
                            <Route path="/alternate" component={alternateComponent} exact/>
                            <Route component={DefaultRoutes}/>
                        </Switch>
                    </div>
                </BrowserRouter>
            </Provider>
        )
    }
}

So with this setup, you can see that the DefaultRoutes will always use Navbar. But that will not be the case for the Route with path "alternate." Essentially, just wrap your Routes that you want to have "normal" display behavior in DefaultRoutes. And define any other Routes outside of that collection. This works thanks to Switch, which will render the routes exclusively.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM