[React] Scroll to Top 버튼 만들기

예빈·2023년 4월 4일
2

React

목록 보기
4/6
post-thumbnail

프로젝트 때 사이트에 무한스크롤 기능을 넣었더니 사이트 최상단으로 스크롤하는 버튼이 필요해졌다.
내가 원하는 최상단 스크롤 버튼의 기능은 다음과 같았다.

  1. Framer-motion 라이브러리를 써서 나타나고 사라질 때 애니메이션이 적용되게 할 것
  2. 스크롤을 아래로 내릴 때 버튼이 나타나고, 위로 올리면 사라질 것
  3. 메인 페이지에서 스크롤을 내리지 않았을 때는 노출되지 않을 것
  4. 버튼을 누르면 부드럽게 스크롤

효율이 좋다고는 할 수는 없겠지만 어쨌든 구현에는 성공했다.

// import 및 필요하지 않은 부분은 생략함

const Home = () => {
  const [btnView, setBtnView] = useState(false);
  const scrollRef = useRef(0);
  
  useEffect(() => {
    const timer = setInterval(() => {
      window.addEventListener("scroll", handleScroll);
    }, 100);
    return () => {
      clearInterval(timer);
      window.removeEventListener("scroll", handleScroll);
    };
  }, []);
  
  ...

  const handleScroll = () => {
    if (window.scrollY > scrollRef.current) {
      setBtnView(true);
    } else {
      setBtnView(false);
    }
    scrollRef.current = window.scrollY;
  };

  const scrollToTop = () => {
    window.scrollTo({
      top: 0,
      behavior: "smooth",
    });
  };
  
  ...
  
  return (
  <HomeWrapper>
    ...
    <AnimatePresence>
        {btnView ? (
          <ScrollToTopBtn
            initial={{ opacity: 0, y: 50 }}
            animate={{
              opacity: 1,
              y: 0,
            }}
            exit={{ opacity: 0, y: 50 }}
            onClick={scrollToTop}
          >
          </ScrollToTopBtn>
        ) : null}
      </AnimatePresence>
  </HomeWrapper>
  )
}

우선 useEffect 안에서 타이머를 등록해준다. 이 과정을 통해 특정 시간마다 이벤트를 감지할 수 있게 된다.
그리고 위처럼 작성한 handleScroll() 함수 안에서 window.scrollYconsole.log로 출력해 보면

이렇게 스크롤 위치가 출력되는 것을 확인할 수 있다.
나는 scrollRef를 설정해 두고, scrollRef와 현재 window.scrollY를 비교해서 스크롤이 내려갔다고 판단되면 btnViewtrue로 설정해주었다.
그런 다음 scrollRef를 업데이트한다.

scrollToTop() 은 버튼을 눌렀을 때 최상단 스크롤을 실행해준다.
behavior: "smooth" 속성을 주면 부드럽게 스크롤된다.

지금 코드는 Framer-motion 라이브러리를 써서 애니메이션을 적용했기 때문에 return 쪽 코드가 조금 복잡한데, 단순히 노출만 하는 정도라면

return (
  <HomeWrapper>
    ...
    {btnView ? (
      <ScrollToTopBtn onClick={scrollToTop}></ScrollToTopBtn>
	) : null}  
  </HomeWrapper>
  )

정도로 충분할 것 같다.

결과물

무한스크롤 때문에 스크롤바만 보면 조금 어색할 수 있지만, 스크롤 버튼은 정상적으로 작동하고 있다.

0개의 댓글