10

I want to reuse a menu I made in react with react-router-dom, but this time in nextjs. The goal is to change the state of the menu to 'false' and the menuName to 'menu' when I click on a link inside the menu.

I use a useEffect function to listen history :

//use effect for page changes
  useEffect(() => {
    //listen for page changes
    history.listen(() => {
      setState({ clicked: false, menuName: "Menu" })
    })
  })

and wrapped my component with withRouter :

import { withRouter } from 'next/router'
[...]
export default withRouter(Header);

Unfortunately, it prints :

TypeError: Cannot read property 'listen' of undefined

Should I better use 'useRouter' to solve this problem? How?

Thank you ;)

Rom-888
  • 681
  • 2
  • 9
  • 30
  • 2
    You can subscribe to a variety of router change events see: [Nextjs: Router Events](https://nextjs.org/docs/api-reference/next/router#routerevents) – pilchard Jan 25 '21 at 14:34

2 Answers2

19

It worked that way :

Nextjs : Router Events

import { useRouter } from "next/router";

...

const router = useRouter()
  useEffect(() => {
    const handleRouteChange = (url) => {
      console.log(
        `App is changing to ${url}`
      )
      setState({ clicked: false, menuName: "Menu" })
    }

    router.events.on('routeChangeStart', handleRouteChange)

    // If the component is unmounted, unsubscribe
    // from the event with the `off` method:
    return () => {
      router.events.off('routeChangeStart', handleRouteChange)
    }
  }, [])
Rom-888
  • 681
  • 2
  • 9
  • 30
0
import { useState, useEffect } from "react";
import { Layout, PageLoading } from ".";
import { useRouter } from "next/router";

const LayoutContainer = ({ pageProps, Component, store, setDeviceWidthAction }) => {
  const router = useRouter();
  const [pageLoading, setPageLoading] = useState(true);

  useEffect(() => {
    setDeviceWidthAction(window.innerWidth);
    setPageLoading(false);
  }, []);

  useEffect(() => {
    const handleStart = (url) => {
      setPageLoading(true);
    };

    const handleStop = () => {
      setPageLoading(false);
    };

    router.events.on("routeChangeStart", handleStart);
    router.events.on("routeChangeComplete", handleStop);
    router.events.on("routeChangeError", handleStop);

    return () => {
      router.events.off("routeChangeStart", handleStart);
      router.events.off("routeChangeComplete", handleStop);
      router.events.off("routeChangeError", handleStop);
    };
  }, [router]);

  if (pageLoading) return <PageLoading />;
  return <Layout {...{ pageProps, Component, store, pageLoading }} />;
};

export default LayoutContainer;
Chukwuemeka Maduekwe
  • 6,687
  • 5
  • 44
  • 67