NextJS는 useParams, useSearchParams와 같이 url에 접근하기 위한 함수를 제공한다.
하지만 Hash(#)에 접근할 수 있는 함수는 찾지 못했다.
따라서 window 객체를 통해 접근했다.
console.log(window.location.hash)
구글링을 하면 useHash라는 Custom Hook을 발견할 수 있다.
hashchange 이벤트를 감지해서 hash를 업데이트하는 방식이다.
예상 외로 잘 동작하지 않는다.
'use client';
import { useEffect, useState } from 'react';
const getHash = () =>
typeof window !== 'undefined'
? decodeURIComponent(window.location.hash.replace('#', ''))
: undefined;
export default function useHash() {
const [hash, setHash] = useState(getHash());
useEffect(() => {
const handleHashChange = () => {
setHash(getHash());
};
window.addEventListener('hashchange', handleHashChange);
return () => {
window.removeEventListener('hashchange', handleHashChange);
};
}, []);
return hash;
};
useRouter를 사용하여 Hash를 변경해도 이벤트가 발생하지 않기 때문이다.
window.location.hash에 직접 할당해도 동작하지 않는데, 아래와 같이 코드를 변경하면 정상적으로 동작한다.
window.addEventListener('hashchange', handleHashChange, false);
기존 실패의 원인은 이벤트가 window까지 전파되지 않은 것으로 생각된다.
그러나 false를 추가하더라도 useRouter를 사용하여 hash를 변경하면 여전히 이벤트가 발생하지 않는다.
다른 방법도 소개되어 있다. useParams의 return 값을 useEffect 의존성 배열에 추가하는 것이다.
'use client';
import { useEffect, useState } from 'react';
const getHash = () => window ? decodeURIComponent(window.location.hash.replace('#', '')) : undefined;
export default function useHash() {
const [hash, setHash] = useState(getHash());
const params = useParams();
useEffect(() => {
setHash(getHash());
}, [params]);
return hash;
};
hash가 바뀌어도 params가 바뀌진 않기에 작동하지 않는다.
hash 변경 시, hash 상태를 업데이트하는 함수도 고려해 보았다.
export default function useHash() {
const [hash, setHash] = useState(getHash());
const params = useParams();
const changeHash = (hash: string) => {
router.push(hash);
setHash(hash);
};
return { hash, changeHash };
};
이는 체택하지 않았다.
상위 컴포넌트에서 hash를 사용하고, 하위 컴포넌트에서 hash를 변경하는 경우, changeHash를 하위 컴포넌트로 전달해야 하기 때문이다.