15

If we stick window.location.hash in useEffect, it will always erroneously return '0'. Apparently it has to do with SSR.

I need to reliably be able to get the hash portion of the URL for my project. How should I best go about it?

geoyws
  • 3,326
  • 3
  • 35
  • 47
  • 1
    just use `next/router` and `router.asPath` – Nico Aug 30 '21 at 15:26
  • It seems that [having the hash fragment on `router.asPath` is not intended](https://github.com/vercel/next.js/issues/25202#issuecomment-966658956) and from that thread I gather it might be removed in the future? – Jeroen Jul 10 '22 at 20:34

2 Answers2

14

Server side code needs to wait until the code is loaded in the browser to use browser APIs.

Vanilla js server-side compatible

const [isMounted, setMounted] = useState(false);
  
useEffect(() => {
 if (isMounted) {
  console.log('hash', window.location.hash);
 } else {
  setMounted(true);
 }
}, [isMounted]);

if(!isMounted) return <>Loading...</>;

Using next/router

import { useRouter } from 'next/router';

const { asPath } = useRouter();

useEffect(()=>{
 const hash = asPath.split('#')[1];
}, [ asPath ]);

FYI you're code shouldn't return a zero. The first culprit that comes to mind is when a shorthand condition is used without an else.

window && window.location.hash

this should have an else

(window && window.location.hash) || null

or

window && window.location.hash ? window.location.hash : null
Sean W
  • 5,663
  • 18
  • 31
2

Extending @Sean W's answer, if you want to get a specific hash value from a hash key, you can use URLSearchParams:

// example path: /#error=unauthorized_client&error_code=401error_description=Something+went+wrong

import { useRouter } from 'next/router';

const { asPath } = useRouter();

useEffect(() => {
  const hash = (asPath as string).split("#")[1]; // error=unauthorized_client&error_code=401error_description=Something+went+wrong
  const parsedHash = new URLSearchParams(hash);
  const errorHash = parsedHash.get("error_description"); // Something went wrong
}, []); // `asPath` omitted from dependencies as ESLint states it won't change
fredrivett
  • 5,419
  • 3
  • 35
  • 48