Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Close Navigation Menu on Route Change

With react-router-dom, how can I detect when the user navigates to a new page?

I'm currently using "react-router-dom": "^4.2.2" and "react": "^15.6.1". I want to close my mobile navigation menu when the user has selected a new target URL, but I'm having trouble detecting when the route has changed.

Is there a callback I can hook into for react-router-dom? I would like to be able to call code along the lines of location.onChange(() => { this.state.collapsed = true; })

My current code is as follows:

Component:

class Leftnav extends Component {

 constructor() {
    super();
    this.state = {
      collapsed: true,
    };
  }

  toggleMenu = () => {
    this.setState({
      collapsed: !this.state.collapsed,
    })
  };

  render() { ... { */html here/* } ... };
};

Template:

<ul className={"leftnav-collapse " + (this.state.collapsed ? 'collapsed' : '')}>
    <li><NavLink to={`/events`} activeClassName="current">Events</NavLink></li>
    <li><NavLink to={`/people`} activeClassName="current">People</NavLink></li>
</ul>

Screenshot:

enter image description here

like image 606
Alex Johnson Avatar asked Sep 15 '17 16:09

Alex Johnson


2 Answers

This comes 4 years too late for the OP, however, I ended up here looking for a solution to the exact problem (albeit with newer versions of react and react-router-dom) so adding my solution here for others solving this problem.

When using functional components (which would be the recommended approach today), we can create a solution using useLocation (from react-router-dom) and useEffect (from react) hooks. A component like the following would close the menu on navigation.

function LeftNav() {
  const [isOpen, setOpen] = useState(false);
  const {pathname} = useLocation();

  useEffect(() => {
    setOpen(false); // Close the navigation panel
  }, [ pathname ]);
  
  return ( /* your jsx */ );
}

A short explanation: In the above component, we obtain the location object from useLocation hook and extract current pathname from there. The value of pathname is going to be updated on user navigation. The useLocation hook also takes care of re-rendering your component (due to state update within hook) whenever that happens. All we need to do after that is create an useEffect hook that closes the menu when pathname changes.

This pattern can be used to take any action in a component based on client side navigation.

like image 54
d_shiv Avatar answered Sep 30 '22 14:09

d_shiv


<NavLink to={`/events`} 
         activeClassName="current"
         onClick={this.toggleMenu}
    >Events</NavLink>

You may need to also update the toggleMenu function to prevent the default click action, now that a click handler is applied.

toggleMenu = (e) => {
    if (e) {
        e.preventDefault();
    }
    this.setState({collapsed: !this.state.collapsed});
}
like image 28
Jake Haller-Roby Avatar answered Sep 30 '22 13:09

Jake Haller-Roby