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?
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?
 
    
    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
 
    
    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
