개발👩‍💻/프론트엔드

next: link # anchor 사용하기

gigibean 2022. 3. 31. 22:01
728x90

next link로 # 해시 앵커를 사용하니 제대로 작동하지 않았다.

 

내비에서 해당 #아이템을 클릭하거나 스크롤이되어 #아이템에 해당하는 곳이 observer된다면 url또한 자동으로 업데이트 되도록하고 뒤로가기를 누른다면 replace로 #관련 주소는 히스토리로 담지 않고 바로 전페이지로 이동하게 하는 것이 목표였다.

 

우선 next link 에서 #해시 앵커를 사용하기 위해서

if (location.hash) location = location;

위와 같이 해주면 된다.

 

활성화된 내비 아이템과 내비가 가리키는 컴포넌트를 state로 관리하고

 

클릭할 때나 페이지 #이 포함된 url로 처음 들어올 때만 해당 앵커가 가리키고 있는 곳으로 스크롤해야 하기 때문에 

useEffect(() => {
// 처음 들어왔을 때
if (location.hash) location = location;
}, [])

// nav item 클릭했을 때
const onClick = useCallback((id) => {
	setAnchorId(id);
    if (location.hash) location = location;
}, [])

 

위와 같이 관련 부분에서 location에 할당해주면 된다.

 

그리고 achorId가 변할 때마다 router를 아래와 같이 변경해주었다.

(anchorId가 변하는 건 전역으로 관리해서 각 anchor가 가리키는 컴포넌트를 intersection observer를 이용해 뷰포트에 intersect되면 anchorId도 변경되도록 해주었다)

  useEffect(() => {
    // next link # anchor replace + url 변경
    router.replace(`#${anchorId}`);
  }, [anchorId]);

 

이렇게 anchorId를 전역으로 관리하고 있기 때문에 anchorId를 해당 컴포넌트가 언마운트될 때 anchorId도 초기화 시켜주어야 한다.

그렇지 않으면 다시 페이지로 돌아오거나 같은 url, 다른 params를 가진 다른 페이지로 들어가게 된다면 #에 마지막으로 저장한 anchorId가 대입되어 들어온다.

 

useEffect(() => {
// 처음 들어왔을 때
if (location.hash) location = location;
return () => {setAnchorId("")}
}, [])
반응형