포스트 글이 길거나 블로그, 프로젝트 갯 수가 많아지면 스크롤이 발생해 상단 이동 버튼을 배치하는게 좋을 것 같아 추가해보았다.
상단 이동 버튼
window.scrollTo(xpos, ypos, behavior:'auto'}) ****를 사용하면 원하는 위치로 이동 시킬 수 있다.
behavior의 값에는 auto, instant, smooth가 있다. (문자이므로 따옴표가 필요하다.)
auto는 기본 값이며, 바로 위치로 이동한다. instant도 같은 동작을 한다.
smooth는 부드럽게 이동하는 애니메이션 효과를 보여준다.
⇒ 부드럽게 상단 위치하기 위해서 클릭 시 window.scrollTo({ top: 0, behavior: "smooth" }); 실행되게 했다.
import { useEffect, useState } from "react";
import { HiChevronUp } from "react-icons/hi";
export default function MoveToTop() {
const moveToTop = () => {
window.scrollTo({ top: 0, behavior: "smooth" });
};
return (
<div
onClick={moveToTop}
className="fixed bottom-7 right-4 lg:right-10 p-2 z-20 cursor-pointer hover:scale-90 transition-all duration-500 rounded-full bg-[#2c82f2]"
>
<HiChevronUp className="text-2xl text-white" />
</div>
);
}
상단 이동 버튼 + 일정 스크롤 높이에서 등장
추가로 스크롤 브라우저 최 상단에서는 상단 이동 버튼이 필요 없기 때문에 일정 스크롤 높이에서 부터 상단 이동 버튼이 등장했으면 좋을 것 같았다.
useState 를 활용해 버튼의 상태 값을 css에 적용했다.
showTopBtn ? "opacity-100 visible" : "opacity-0 invisible" showTopBtn가 true면 보이게 적용했다.
*visible 는 visibility: visible; / invisible 는 visibility: hidden; (tailwind 표기)
이제 필요한 거는 원하는 시점에서 showTopBtn가 true로 변하게 해야 됩니다.
- useEffect 훅을 활용하여 컴포넌트가 마운트될 때 실행됩니다.
- 스크롤 이벤트가 발생할 때마다 호출 되는 showBtnClick 함수가 정의합니다.
- showBtnClick 함수 내에서 현재 스크롤 위치 (window.scrollY) 를 확인하고, 위치가 400보다 크면setShowTopBtn(true)를 호출하고 그렇지 않으면 setShowTopBtn(false) 를 호출합니다.
- window.addEventListener("scroll", showBtnClick);를 통해 스크롤 이벤트에 대한 리스너가 등록되어 스크롤이 발생할 때마다 showBtnClick 함수가 호출됩니다.
- 컴포넌트가 언마운트되면 return 블록 내의 함수가 실행되어 window.removeEventListener("scroll", showBtnClick); 를 통해 등록된 스크롤 이벤트 리스너를 제거하여 메모리 누수를 방지합니다.
useEffect(() => {
const showBtnClick = () => {
if (window.scrollY > 400) {
setShowTopBtn(true);
} else {
setShowTopBtn(false);
}
};
window.addEventListener("scroll", showBtnClick);
return () => {
window.removeEventListener("scroll", showBtnClick);
};
}, []);
전체 코드
import { cls } from "libs/utils";
import { useEffect, useState } from "react";
import { HiChevronUp } from "react-icons/hi";
export default function MoveToTop() {
const [showTopBtn, setShowTopBtn] = useState(false);
const moveToTop = () => {
window.scrollTo({ top: 0, behavior: "smooth" });
};
useEffect(() => {
const showBtnClick = () => {
if (window.scrollY > 400) {
setShowTopBtn(true);
} else {
setShowTopBtn(false);
}
};
window.addEventListener("scroll", showBtnClick);
return () => {
window.removeEventListener("scroll", showBtnClick);
};
}, []);
return (
<div
onClick={moveToTop}
className={cls(
showTopBtn ? "opacity-100 visible" : "opacity-0 invisible",
"fixed bottom-7 right-4 lg:right-10 p-2 z-20 cursor-pointer hover:scale-90 transition-all duration-500 rounded-full bg-[#2c82f2]"
)}
>
<HiChevronUp className="text-2xl text-white" />
</div>
);
}
특정 영역 안에서 상단 이동
다른 프로젝트에서 탭이 있는 모달 창을 만들던 중 스크롤이 생기는 모달이어서 탭 클릭 시 자동으로 위에서 부터 다시 시작하게 만들어야 했다.
DOM요소에 접근하기 위해 사용되는 React Hook 인 useRef 를 활용하여 해당 영역을 참조한다.
아래 코드에서는 참조된 영역의 scrollTop이 0이 아니면 수직 스크롤 바의 위치를 0으로 변경한다.
import { useState, useEffect, useRef } from "react";
export default function Ex() {
const [modalTab, setModalTab] = useState(1);
const modalInfoModal = useRef<HTMLDivElement>(null);
const selectModalTabHandler = (order: number) => {
setModalTab(order);
if (modalInfoModal.current.scrollTop !== 0) { // 상단으로 이동
modalInfoModal.current.scrollTop = 0;
}
};
return (
<Modal>
<ul>
<li
onClick={() => selectModalTabHandler(1)}
className={modalTab === 1 ? "on" : ""}
>
탭 1
</li>
<li
onClick={() => selectModalTabHandler(2)}
className={modalTab === 2 ? "on" : ""}
>
탭 2
</li>
</ul>
<div
ref={modalInfoModal}
>
{modalTab === 1 ? (
<div className="topRank"> 탭 1 content</div>
) : (
<div className="topRank"> 탭 2 content</div>
)}
</div>
<Modal/>
)
}
'React' 카테고리의 다른 글
ExcelJS 다운로드 & 엑셀 파일 업로드 (0) | 2024.08.24 |
---|---|
apexcharts (0) | 2024.08.24 |
React에서 Lottie 사용하기 (0) | 2024.08.24 |
React Datepicker (0) | 2024.08.23 |
react 모달 밖 클릭 시 닫기 (0) | 2024.08.23 |