skip to Main Content

Hoping someone can help! I’m building a nextJS website and wanting to incorporate some javascript. I want this javascript to run each time a user navigates to a separate page.

Let’s say I want to log something to the console each time.

I’ve written a script here using React. I believe I have to use useEffect?

import React, { useEffect } from 'react'

const Alerter = () => {
  useEffect(() => {
    console.log("Page Rendered !!");
  }, [])
}

export default Alerter

Then, do I have to import that on each individual page.js, and then also run it? Such as the below


import buttonStyles from '../components/global/button.module.css'

//Scripts
import Alerter from '../scripts/runAlert'

export default function LoginPage() {
  return (
    <div>
      <form>
        <button className={buttonStyles.button} formAction={login}>Log in</button>
      </form>
      <Alerter />
    </div>
  )
}

Is there a cleaner way?

3

Answers


  1. Chosen as BEST ANSWER

    I ended up doing the following. I created a file called 'clientApplication' with the following code

    "use client";
    import { useEffect } from "react";
    import { usePathname } from 'next/navigation';
    
    import FadeInElements from './scripts/FadeInElements'
    
    export default function ClientApplication({ children }) {
      const pathname = usePathname();
    
      useEffect(() => {
        FadeInElements(pathname);
      });
    
      return children;
    }
    

    Then in my layout.js I wrapped this around my {children}

    export default function RootLayout({ children }) {
    
      return (
        <html lang="en">
          <body data-theme="light">
            <ClientApplication>
              {children}
            </ClientApplication>
          </body>
          <GoogleAnalytics gaId="G-7GTMYC6GZP" />
          <Analytics />
          <SpeedInsights />
        </html>
      )
    

    This seems to be working okay. Do you see any concerns with it?


  2. The _app.js file in Next.js acts as the entry point for all pages. You can add your JavaScript logic there to ensure it runs on every page navigation.
    Try this in your _app.js

    import { useEffect } from 'react';
    import { useRouter } from 'next/router';
    
    const App = ({ Component, pageProps }) => {
      const router = useRouter();
    
      useEffect(() => {
        const handleRouteChange = (url) => {
          console.log(`Navigated to: ${url}`);
        };
    
        router.events.on('routeChangeComplete', handleRouteChange);
    
        return () => {
          router.events.off('routeChangeComplete', handleRouteChange);
        };
      }, [router.events]);
    
      return <Component {...pageProps} />;
    };
    
    export default App;
    Login or Signup to reply.
  3. Let’s start with fixing your current component. It needs to return something:

    const Alerter = () => {
      useEffect(() => {
        console.log("Page Rendered !!");
      }, []);
      
      return null; // Must return something
    };
    

    However, rather than adding this to every page, here are better approaches:

    Layout Component Approach Since Next.js uses a shared Layout component, you could add your effect there to run on all pages:

    // app/layout.js
    export default function RootLayout({ children }) {
      useEffect(() => {
        console.log("Page Rendered !!");
      }, []);
    
      return (
        <html>
          <body>{children}</body>
        </html>
      );
    }
    

    Custom App Approach You could create a custom _app.js (Pages Router) or modify your root layout (App Router) to handle this:

    // pages/_app.js (Pages Router)
    function MyApp({ Component, pageProps }) {
      useEffect(() => {
        console.log("Page Rendered !!");
      }, []);
    
      return <Component {...pageProps} />;
    }
    
    export default MyApp;
    

    Router Events Approach If you specifically want to track navigation events, you can use Next.js router events:

    // app/layout.js
    'use client';
    import { usePathname } from 'next/navigation';
    
    export default function RootLayout({ children }) {
      const pathname = usePathname();
      
      useEffect(() => {
        console.log(`Navigated to: ${pathname}`);
      }, [pathname]);
    
      return (
        <html>
          <body>{children}</body>
        </html>
      );
    }
    

    The Router Events approach is particularly good because:

    • It will actually trigger on route changes
    • You only need to set it up once
    • It gives you access to the new route information

    Which approach would work best depends on exactly what you’re trying to achieve. Are you specifically trying to track navigation events, or do you need to run some other kind of initialization on each page load?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search