reactjsurlnext.jsurl-fragment

How to detect change in the URL hash in Next.js?


How do we detect a change in the URL hash of a Next.js project?

I don't want to reload my page every time the slug changes.

I cannot use <Link> since all of my data comes from DB

Example: When clicking on an tag from
http://example/test#url1
to
http://example.com/test#url2

Tried the below, but this seems to work for path change only.

import React, { useEffect,useState } from 'react';
import { useRouter } from 'next/router'

const test = () => {
    const router = useRouter();

    useEffect(() => {
        console.log(router.asPath);
    }, [router.asPath]);

    return (<></>);
};

export default test;

Solution

  • You can listen to hash changes using hashChangeStart event from router.events.

    const Test = () => {
        const router = useRouter();
    
        useEffect(() => {
            const onHashChangeStart = (url) => {
                console.log(`Path changing to ${url}`);
            };
    
            router.events.on("hashChangeStart", onHashChangeStart);
    
            return () => {
                router.events.off("hashChangeStart", onHashChangeStart);
            };
        }, [router.events]);
    
        return (
            <>
                <Link href="/#some-hash">
                    <a>Link to #some-hash</a>
                </Link>
                <Link href="/#some-other-hash">
                    <a>Link to #some-other-hash</a>
                </Link>
            </>
        );
    };
    

    If you're not using next/link or next/router for client-side navigation (not recommended in Next.js apps), then you'll need to listen to the window's hashchange event.

    Your useEffect would look like the following.

    useEffect(() => {
        const onHashChanged = () => {
            console.log('Hash changed');
        };
    
        window.addEventListener("hashchange", onHashChanged);
    
        return () => {
            window.removeEventListener("hashchange", onHashChanged);
        };
    }, []);