유저를 페이지 최상단으로 이동시키는 top button을 만들어보자.
지난 포스팅(Throttle로 Sticky Header 구현하기)에서 구현한 scorll 이벤트 핸들링의 연장선으로 이번에는 유저가 scroll을 했을 때 특정 UI가 노출되도록 하는 custom hook을 만들어서 구현해보고자 한다.
기능 구현에 앞서 top button view를 만들어보자. 보통의 top button의 view 조건은 다음과 같다.
버튼을 좌측 하단에 '고정'시키려면 position 속성을 정해줘야한다. 처음에는 position 속성을 absoulte를 사용하려 했으나 부모 영향을 받게되어서 내가 원하는 위치에 고정시키기 어려웠다. 그래서 스크롤 할 때 부모 위치와 상관없이 항상 그 자리에 고정시킬 수 있는 fixed
속성을 사용하고 botton과 right를 각각 2rem
으로 정해줬다.
화면을 최상단으로 이동시키는 로직은 간단하다. element의 최상단에서 현재 보이는 콘텐츠 상단까지의 거리를 가지고 있는 scrollTop 속성값을 0으로 정해주면 된다. moveToTop 함수를 만들고 top button 을 클릭했을 때 moveToTop 함수가 호출되도록 적용해준다.
const moveToTop = () => (document.documentElement.scrollTop = 0);
.
.
.
<TopButton onClick={moveToTop}/> //이와 같이 적용
Top Button 또한 유저가 스크롤을 했을 때 나타나고 다시 최상단으로 갔을 때 사라져야하기 때문에 지난 포스팅(Throttle로 Sticky Header 구현하기)에서 sticky header를 만들 때 사용했던 로직을 재사용하였다. scroll 이벤트는 특정 시간 동안 1번만 호출되도록 하여 불필요한 함수 호출을 최소화하는 방식으로 구현했다. 하지만 이 로직은 sticky header과 top button 같이 scroll에 따라 요소를 toggle하는 모든 컴포넌트에 재사용될 수 있는 로직이기 때문에 scroll에 따른 toggle 조건을 만드는 custom hook로 리팩토링하였다.
외부에서 initial state를 주입받아 현재 scroll 여부 상태를 반환해주는 custom hook이다.
import { useEffect, useState } from "react";
import throttle from "util/throttle";
const useScrollToggle = (initState: Boolean = false) => {
const [scrollFlag, setScrollFlag] = useState(initState);
const updateScroll = () => {
const { scrollY } = window;
scrollY > 10 ? setScrollFlag(true) : setScrollFlag(false);
};
const handleScroll = throttle(updateScroll, 100);
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return scrollFlag;
};
export default useScrollToggle;
scroll에 따른 toggle과 관련된 로직을 custom hook안에 숨김으로써 해당 컴포넌트에서는 컴포넌트가 해야할 로직만 보여주는 깔끔한 구조로 개선되었다.
고수시네요.. 잘 보고갑니다..