import { useEffect, useRef } from "react";
export default function Home() {
const scrollRef = useRef(null);
useEffect(() => {
const handleScroll = (e: React.WheelEvent) => {
const scrollTop = scrollRef.current.scrollTop;
const viewHeight = window.innerHeight;
const deltaY = e.deltaY;
console.log(scrollTop, viewHeight);
if (scrollRef.current) {
console.log(e);
// down wheel event
if (deltaY > 0) {
if (scrollTop < viewHeight) {
console.log("1page");
scrollRef.current.scrollTo({
top: viewHeight * 2,
behavior: "smooth",
});
} else if (scrollTop < viewHeight * 2) {
console.log("2page");
scrollRef.current.scrollTo({
top: viewHeight * 2,
behavior: "smooth",
});
}
}
// up wheel event
if (deltaY < 0) {
if (scrollTop < viewHeight) {
console.log("1page");
scrollRef.current.scrollTo({
top: 0,
behavior: "smooth",
});
} else if (scrollTop < viewHeight * 2) {
console.log("2page");
scrollRef.current.scrollTo({
top: 0,
behavior: "smooth",
});
}
}
}
};
if (scrollRef.current) {
scrollRef.current.addEventListener("wheel",
handleScroll);
}
return () => {
if (scrollRef.current) {
scrollRef.current.removeEventListener("wheel",
handleScroll);
}
};
}, []);
return (
<FullPageScrollWrapper ref={scrollRef}>
<FullPageElement style={{ background: "red" }}>1</FullPageElement>
<FullPageElement style={{ background: "blue" }}>2</FullPageElement>
</FullPageScrollWrapper>
);
}
이렇게 만들고 보니, 실제 라이브러리 처럼 스크롤 섹션 요소만 넣어주면 개수의 상관없이 스크롤이 가능하게 만들어보고 싶은 욕심이 생겨서 위의 코드를 개선해봤다.
import { useEffect, useRef } from "react";
export default function Home() {
const scrollRef = useRef(null);
const pageSection = [
<FullPageElement style={{ background: "red" }}>1</FullPageElement>,
<FullPageElement style={{ background: "green" }}>2</FullPageElement>,
<FullPageElement style={{ background: "blue" }}>3</FullPageElement>,
<FullPageElement style={{ background: "black" }}>4</FullPageElement>,
];
useEffect(() => {
const handleScroll = (e: React.WheelEvent) => {
const scrollTop = scrollRef.current.scrollTop;
const viewHeight = window.innerHeight;
const deltaY = e.deltaY;
console.log(scrollTop, viewHeight);
if (scrollRef.current) {
// down wheel event
if (deltaY > 0) {
for (let i = 0; i < pageSection.length; i++) {
if (
scrollTop >= viewHeight * i &&
scrollTop <= viewHeight * (i + 1)
) {
scrollRef.current.scrollTo({
top: viewHeight * (i + 1),
behavior: "smooth",
});
}
}
}
// up wheel event
if (deltaY < 0) {
for (let i = 0; i < pageSection.length; i++) {
if (
scrollTop >= viewHeight * i &&
scrollTop <= viewHeight * (i + 1)
) {
scrollRef.current.scrollTo({
top: viewHeight * (i - 1),
behavior: "smooth",
});
}
}
}
}
};
// 이벤트 등록
if (scrollRef.current) {
scrollRef.current.addEventListener("wheel",
handleScroll);
}
// 메모리 최적화를 위해 이벤트 삭제 (선택사항)
return () => {
if (scrollRef.current) {
scrollRef.current.removeEventListener("wheel",
handleScroll);
}
};
}, []);
return (
<FullPageScrollWrapper ref={scrollRef}>
{pageSection}
</FullPageScrollWrapper>
);
}
배열 형식의 pageSection
에 원하는 스크롤 섹션의 HTML요소만 넣어주면 잘 작동하는 모습을 볼 수 있다.
안녕하세요. 저도 동일하게 적용해 보았는데, 이동이 되지 않네요.
혹시 FullPageElement, FullPageScrollWrapper 컴포넌트 설정은 어떻게 하셨는지 알 수 있을까요?
'scrollRef.current' is possibly 'null'.ts(18047) 오류가 발생해 useRef의 타입은 any로 지정했습니다.