Routes not working in react router v4

ApurvG Source

I am trying to work with react router v4. I have a application where I have two pages: Login page and App Page. In my app page I have three sections: Header, sidebar and content section. This is what I want

  1. Landing page should be Login page
  2. Once user clicks login button, user should land to App Page. (For testing I haven't included user authentication)
  3. Now in my App page, I can show one of the 3 components (which I have already made) based on what user clicks on sidebar. So Sidebar and header should always be visible and content division should change it's component based on what user click on sidebar.

This is how I have setup my routes right now

class Root extends Component {
    render() {
        return (
            <div>
                <main>
                    <Route exact path="/" component={LoginPage} />
                    <Route exact path="/app" component={App}>
                    </Route>
                </main>
            </div>
        );
    }
}

And App.js

class App extends Component {
  render() {
    return (
      <div>
        <Header/>
          <Sidebar/>
        <main>
          <Switch>
          <Route exact path="/trivia" component={TriviaPanel}/>
            <Route exact path="/image" component={ImagePanel}/>
          </Switch>
        </main>
      </div>
    );
  }
}

MenuPanel.js (from where I go to trivia and image)

import React, { Component } from 'react';
import { push } from 'react-router-redux'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'

const styles = require('./sidebar.css');

class MenuPanel extends Component {
    render() {
        return (
            <div>
                <div className="navbar-side">
                    <div className="tessact-logo"></div>
                    <div className="navbar-item active" onClick={() => this.props.toTriviaPage()}>
                        <a className="navbar-item-link"><span className="fa fa-comment"></span> TRIVIA</a>
                    </div>
                    <div className="navbar-item" onClick={() => this.props.toImagePage()}>
                        <a className="navbar-item-link"><span className="fa fa-picture-o"></span> IMAGES</a>
                        <div className="navbar-item-inside">
                            <a className="navbar-item-inside-link">PERSONSS</a>
                            <a className="navbar-item-inside-link">BRANDS</a>
                            <a className="navbar-item-inside-link">OBJECTS</a>
                        </div>
                    </div>
                    <div className="navbar-item">
                        <a className="navbar-item-link"><span className="fa fa-tags"></span> KEYWORDS</a>
                    </div>
                </div>
            </div>

        );
    }
}


const mapDispatchToProps = dispatch => bindActionCreators({
    toTriviaPage: () => push('/app/trivia'),
    toImagePage: () => push('/app/image')
}, dispatch)


export default connect(
    null,
    mapDispatchToProps
)(MenuPanel)

I want TriviaPanel to be the default view when landed to App. Currently I land to login page and when I click to login, App page is not working in the manner it should. I can't see anything apart from sidebar and header, which also gets disappear when I click something in sidebar (trivia link).

How should I achieve this? In react router v3 there was a nice option of childroutes. What can I do to solve this?

reactjsreact-routerreact-router-v4

Answers

answered 5 months ago Chase DeAnda #1

The problem is in App. You are doing the nesting correctly, but your paths are wrong. Looking at Root the App component lives on /app. So your nested routes should ALSO include the /app prefix in their paths:

class App extends Component {
  render() {
    return (
      <div>
        <Header/>
          <Sidebar/>
        <main>
          <Switch>
            <Route exact path="/app/trivia" component={TriviaPanel}/>
            <Route exact path="/app/image" component={ImagePanel}/>

            {/* Catch-all route for TriviaPanel */}
            <Route component={TriviaPanel}/>
          </Switch>
        </main>
      </div>
    );
  }
}

Update:

Ah, apparently this is a known issue with react-router-redux: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/redux.md#blocked-updates

You need to wrap your connected component with the withRouter HOC from react-router-dom:

// before
export default connect(
    null,
    mapDispatchToProps
)(MenuPanel)

// after
import { withRouter } from 'react-router-dom'
export default withRouter(connect(
    null,
    mapDispatchToProps
)(MenuPanel))

comments powered by Disqus