javascriptreactjsnext.js

Javascript in NextJS - How To Structure?


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.

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?

'use client'
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 { login } from './actions'

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?


Solution

  • 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:

    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?