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를 하위 컴포넌트로 전달해야 하기 때문이다.