Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

listen for router change via useEffect in NextJS

I am trying to get an useEffect to execute some code when a user changes the page via the navigation.

My problem is that the useEffect does not execute on the route change (does not show up in console). It does only show up on the first initial page load and never after

I used the google analytics example from nextJS

This is my simple _app.tsx

import type { AppProps } from "next/app";
import "./styles/css.scss";
import { useRouter } from "next/dist/client/router";
import { useEffect} from "react";



const Child: React.FC = ({ children }) => {
  return (
    <>
      <div>{children}</div>
    </>
  );
};

const App = ({ Component, pageProps }: AppProps) => {
  const router = useRouter();

  useEffect(() => {

    console.log("called");

  }, [router.events]);
  return (
    <>
      <Child>
        <Component {...pageProps} />
      </Child>
    </>
  );
};
export default App;
like image 437
Maxime Ghéraille Avatar asked Apr 12 '21 17:04

Maxime Ghéraille


People also ask

Can I use useEffect in NextJs?

Adding the useEffect() (or Effect Hook) hook in Next. js is not at bad as one would think. Let's take a look at an example. We will use useEffect to add an event listener to handle when a user scrolls.

How do I transfer data to my NextJs router?

There is no way to pass data between pages with Next's router. You would have to either use query strings as you mentioned, sessionStorage, or a state management option like Redux or React's Context API. You could then put that in your pages/_app.

How do I use react router in NextJs?

Let's now declare a withReactRouter HOC to wrap the application with the proper router: // next/with-react-router. js import React from 'react'; import {BrowserRouter} from 'react-router-dom'; const isServer = typeof window === 'undefined'; export default App => { return class AppWithReactRouter extends React.


3 Answers

I was able to get this working more simply, by listening for changes to router.asPath.

  useEffect(() => {
    console.log('useEffect fired!', {asPath: router.asPath});
  }, [router.asPath]);
like image 181
Matt Muggeridge Avatar answered Oct 22 '22 10:10

Matt Muggeridge


You can use routeChangeStart, routeChangeComplete and routeChangeError events to do some functionality whenever the route is changing.

Here I use NProgress to show slim progress bar, if you want you can try the same thing and get some idea about how its working or you can just log some data, () => { console.log("route change start") }

import '../styles/globals.css'
import 'nprogress/nprogress.css'
import NProgress from 'nprogress'
import { Router } from 'next/dist/client/router'
Router.events.on('routeChangeStart', () => {
  NProgress.start()
})
Router.events.on('routeChangeComplete', () => {
  NProgress.done()
})
Router.events.on('routeChangeError', () => {
  NProgress.done()
})
function MyApp({ Component, pageProps }) {
  return (
    <div>
      <h1 style={{ textAlign: 'center', alignItems: 'center' }}>
        Welcome to my App
      </h1>
      <Component {...pageProps} />
    </div>
  )
}

export default MyApp
like image 40
Faruk Avatar answered Oct 22 '22 12:10

Faruk


Thank to @Faruk answer, I was able to find that it was possible but I had to use those router.events.on inside my hook.

useEffect(() => {
    router.events.on("routeChangeComplete", () => {
      console.log("route change routeChangeComplete");
    });
    return () => {
      router.events.off("routeChangeComplete", () => {
        console.log("stoped");
      });
    };
  }, [router.events]);
like image 37
Maxime Ghéraille Avatar answered Oct 22 '22 11:10

Maxime Ghéraille