0

I have tried for a really long time to figure out how I would go about creating a navigation dropdown using react-router-dom. My problem is that I want to be able to have the current page selected in the dropdown, and my way of doing that is to keep the selected item in the this.state variable of the parent. Here is my code currently in the render() function (I am using react-bootstrap components for the dropdown):

  <Dropdown.Menu className="dropdown-menu-right">
    <MenuItem name="bandList"
      className={(this.state.activeView === "bandList") ? "active" : ""}
      onClick={ this.handleClick } >
      Hitta Band
    </MenuItem>
    <MenuItem name="musiciansList"
      className={(this.state.activeView === "musiciansList") ? "active" : ""}
      onClick={ this.handleClick } >
      Hitta Musiker
    </MenuItem>
  </Dropdown.Menu>

And the handleClick() function:

handleClick(event){
  var name = event.target.name;
  this.setState({
    activeView: name
  })
}

I have read the thread here: Programmatically navigate using react router

But the ways described there is to create a new component and wrap it inside of either withRouter function or a <Route> component, which doensn't work in my case. The problem is that I need to be able to change this.state and navigate to another route when clicking in the menu. I tried creating a new component and wrapping it inside of withRouter() like this:

const BandListNav = withRouter(({history}) => (
  <MenuItem
    name="bandList"
    onClick={() => history.push('/bandList')}
    >
    Hitta Band
  </MenuItem>
));

And then in the parent component the render() function would be:

  <Dropdown.Menu className="dropdown-menu-right">
    <BandListNav
      className={(this.state.activeView === "bandList") ? "active" : ""}
      onClick={ this.handleClick }
    />
  </Dropdown.Menu>

But in this case the this.handleClick function would not get called (I guess it gets overridden by the onClick() function in the BandListNav component.

Basically what I want to do is to change the state of the parent component while at the same time navigating to another route.

Is there any way to do this using react-router-dom (v4)?

Any help appreciated. Thanks in advance!

martin36
  • 2,253
  • 4
  • 18
  • 27
  • https://stackoverflow.com/questions/44127739/programatically-routing-based-on-a-condition-with-react-router/44128108#44128108 – Shubham Khatri Jul 18 '17 at 16:53
  • Is there a reason you need your current view stored in your state? This can easily been determined by window.location.pathname at any time from anywhere. If you're routing on click, you should be using a `` component. – Kyle Richardson Jul 18 '17 at 17:09
  • I need to be able to give the current view the `active` class. But if I can do it using `window.location.pathname` that would probably work. Like writing `className={(window.location.pathname === "/bandList") ? "active" : ""}` instead of what I previously did. – martin36 Jul 18 '17 at 17:21
  • @KyleRichardson Thank you very much. I tried using `window.location.pathname` instead of the state variable and it worked. – martin36 Jul 18 '17 at 17:27
  • You're very welcome! Glad you got what you needed! – Kyle Richardson Jul 18 '17 at 17:34

2 Answers2

0

I implemented what Kyle Richardson said in the comments and it worked as I wanted it to. Here is how I changed the code, for those interested:

  <Dropdown.Menu className="dropdown-menu-right">
    <BandListNav/>
    <MusiciansListNav/>
  </Dropdown.Menu>

And the components became:

const BandListNav = withRouter(({history}) => (
  <MenuItem
    name="bandList"
    onClick={() => history.push('/bandList')}
    className={(window.location.pathname === "/bandList") ? "active" : ""}
    >
    Hitta Band
  </MenuItem>
));

const MusiciansListNav = withRouter(({history}) => (
  <MenuItem
    name="musiciansList"
    onClick={() => history.push('/musiciansList')}
    className={(window.location.pathname === "/musiciansList") ? "active" : ""}
    >
    Hitta Musiker
  </MenuItem>
));

That saved me a lot of time. Thank you very much for the answer and I hope this will help someone else.

martin36
  • 2,253
  • 4
  • 18
  • 27
0

You can 1) allow the NavLink component to manage what menu item is selected using the active property for you, 2) modify what the name of the class is that you'd like to designate as the active class in your css by using NavLink's "activeClassName=" property, or 3) Customize the NavLink component as described in this stackoverflow question.

stonybrooklyn
  • 122
  • 2
  • 10