Source:  Twitter logo

I'm toggling navigation in next.js, it works fine, it's just I want the navigation to close again when the route changes.

For example, if I'm on the home page and toggle the navigation, the navigation opens and shows a link to the about page. If I click that link, I get taken to the about page as expected - but the navigation is still open!

I've tried a few things - I think I want to utilize onRouteChangeComplete(url) but I'm struggling to update the navActive state.

My page.js file:

class Page extends Component {
  state = {
    navActive: false

  toggle = () => {
      navActive: !this.state.navActive

  render() {
    return (
      <ThemeProvider theme={theme}>
        <StyledPage className="full-page-wrapper">
          <Meta />
          <Header navActive={this.state.navActive} toggle={this.toggle} />
          <GlobalStyle />

Then my header file:

class Header extends React.Component {
  render() {
    return (

        <HeaderToggleBar onClick={() => this.props.toggle()} />


So the app starts off with navActive state of false, clicking the HeaderToggleBar element opens and closes the nav. But I need to close the nav when the route changes. I guess I could put the click event on the navigation items within the header (so clicking to a new page toggles) but that seems a bit over the top.

Thank you.

if you're using a functional React component, you can do this:

   const router = useRouter();

   useEffect(() => {
    if (isMenuOpen) {
  }, [router.asPath]);
26 users liked answer #0dislike answer #026
raptoria7 profile pic

Have a look at You should be fine with sth like this in the ctor of your Header component:

  super(props);'routeChangeComplete', (url) => {
21 users liked answer #1dislike answer #121
Rob profile pic

We can use router events to handle this. Refer:

const router = useRouter();
useEffect(() => {'routeChangeComplete', handleRouteChange)
  return () => {'routeChangeComplete', handleRouteChange)
}, []);
9 users liked answer #2dislike answer #29
One Mad Geek profile pic
One Mad Geek

when route changing is happening, next.js is trying to load the other page. A better way to handle the route change, if you are tracking the loading state, keep that loading state true, until the route change is complete.

 const router = useRouter();

 useEffect(() => {
    const handleComplete = () => {
    };"routeChangeComplete", handleComplete);"routeChangeError", handleComplete);

    return () => {"routeChangeComplete", handleComplete);"routeChangeError", handleComplete);
  }, [router]);
2 users liked answer #3dislike answer #32
Yilmaz profile pic


There you can see class component base code. But here I use the functional components to solve this issue.

useEffect(() => {
    const handleRouteChange = () => {
    }'routeChangeStart', handleRouteChange)
}, [])
1 users liked answer #4dislike answer #41
Mahadi Hasan profile pic
Mahadi Hasan

Complete example

Using a functional component.

Triggering on routeChangeStart, so the menu can optionally be animated immediately after clicking.

import { useRouter } from 'next/router';

const Menu = () => {
  const router = useRouter();
  const [show, setShow] = useState(false);

  const hide = useCallback(() => {
  }, [setShow]);

  useEffect(() => {
    // subscribe'routeChangeStart', hide);
    // unsubscribe
    return () =>'routeChangeStart', hide);
  }, [hide,]);

  return show ? <div>menu</div> : null

Managing nesting (TypeScript)

I needed something like this in top level, though I'd share:

interface ContextProps {
  show: boolean;
  setShow: (show: boolean) => void;

export const MenuContext = React.createContext<Partial<ContextProps>>({
  show: false,
  setShow: () => {},
  const [show, setShow] = useState(false);

  return (
    <MenuContext.Provider value={{ show, setShow }}>
1 users liked answer #5dislike answer #51
Webber profile pic

I believe you need to bind your callback. You might also need to add a constructor. Here's an snippet from a project that accepts file uploads.

    class Files extends React.Component {
        // define your constructor and call super before setting state vars
            this.state = {
                uploadStatus: false
            // Bind your callback
            this.handleUploadImage = this.handleUploadImage.bind(this);
            // set other initial vars if needed

            // do stuff with the files

        render () {
            return (
                <div id="fileContainer">
                    <MyDropzone id={this.props.project._id} onDrop={this.handleUploadImage}>
                        {({getRootProps}) => <div {...getRootProps()} />}
0 users liked answer #6dislike answer #60
Brock profile pic

Copyright © 2022 QueryThreads

All content on Query Threads is licensed under the Creative Commons Attribution-ShareAlike 3.0 license (CC BY-SA 3.0).