개발을 하다 보면 일반적인 세로 방향 스크롤이 아닌 아래의 그림처럼 가로 방향으로 넘어가는 스크롤이 필요한 경우가 있습니다.
따라서 이번 글에서 가로 스크롤에 필요한 코드를 정리해보겠습니다.
🐝 전체 코드
아래의 코드는 'useHorizontalScroll.ts'라는 이름의 커스텀 훅으로, 원하는 요소에 가로 스크롤을 적용합니다.
import { useRef, useEffect, useCallback } from 'react';
export const useHorizontalScroll = () => {
const listWrapperRef = useRef<HTMLUListElement>(null);
const handleWheel = useCallback((e: WheelEvent) => {
const container = listWrapperRef.current;
if (container) {
const delta = e.deltaY;
container.scrollLeft += delta;
e.preventDefault();
}
}, []);
useEffect(() => {
const container = listWrapperRef.current;
if (container) {
container.addEventListener('wheel', handleWheel);
return () => {
container.removeEventListener('wheel', handleWheel);
};
}
return () => {};
}, [handleWheel]);
return listWrapperRef;
};
코드는 크게 네 부분으로 나눌 수 있으며 아래에서 자세히 살펴보겠습니다.
🐝 코드 설명
1) 'listWrapperRef' 생성
const listWrapperRef = useRef<HTMLUListElement>(null);
- 스크롤이 적용될 요소는 보통 리스트 요소(<ul>)이므로 useRef 훅을 사용하여 'listWrapperRef' 변수를 생성합니다.
- 해당 ref는 스크롤이 적용될 요소와 연결됩니다.
2) 'handleWheel' 함수 정의
const handleWheel = useCallback((e: WheelEvent) => {
const container = listWrapperRef.current;
if (container) {
const delta = e.deltaY;
container.scrollLeft += delta;
e.preventDefault();
}
}, []);
- 'handleWheel' 함수가 받는 event(e)인 WheelEvent는 사용자의 마우스 휠 이벤트 객체입니다.
- 마우스 휠이 위아래(세로 방향)로 움직인 정도인 deltaY 값을 연결된 요소의 scrollLeft 속성에 더해, 해당 요소가 가로로 스크롤되도록 합니다.
- e.preventDefault()를 호출하여 기본 세로 스크롤 이벤트를 막습니다.
참고로 'const delta'를 정의할 때 'e.detail' 또는 'e.wheelDelta' 속성이 사용되는 경우가 있습니다.
이는 과거에 사용되던 속성으로 최신 브라우저 표준에서는 지원하지 않습니다. 따라서 'deltaX', 'deltaY', 'deltaZ' 속성을 사용하면 됩니다.
3) useEffect로 이벤트 리스너 등록
useEffect(() => {
const container = listWrapperRef.current;
if (container) {
container.addEventListener('wheel', handleWheel);
return () => {
container.removeEventListener('wheel', handleWheel);
};
}
return () => {};
}, [handleWheel]);
- useEffect 훅으로 컴포넌트가 마운트 될 때 'wheel' 이벤트 리스너를 등록하고,
- 원마운트될 때 해당 이벤트 리스너를 제거하여 메모리 누수를 방지합니다.
4) 'listWrapperRef' 반환
return listWrapperRef;
- 마지막으로 앞서 생성한 'listWrapperRef'를 반환하여 가로 스크롤이 필요한 요소에 ref를 연결할 수 있도록 합니다.
🐝 적용하기
원하는 요소에 가로 스크롤을 적용하기 위해 제가 구현한 코드의 일부를 예시로 보겠습니다.
폴더 목록이 <ul> 태그로 감싸져 있고, <li> 태그로 감싸진 폴더 항목들이 map()을 통해 화면에 뿌려집니다.
가로 스크롤과 관련되지 않은 코드는 생략하였습니다.
import { useHorizontalScroll } from '@/lib/hooks';
export const FolderList = () => {
const listWrapperRef = useHorizontalScroll();
//... 생략
return (
<div>
<ul
className="overflow-x-auto scrollbar-hide"
ref={listWrapperRef} // 여기에 연결
>
{folderList.map((folder) => (
<li key={folder.id}>
<Folder folder={folder} />
</li>
))}
</ul>
</div>
);
};
- 위에서 만들어준 'useHorizontalScroll.ts' 파일을 임포트해옵니다.
- useHorizontalScroll() 커스텀 훅에서 반환하는 'listWrapperRef'를 받아옵니다.
- 가로 스크롤을 적용하고 싶은 요소에 ref 속성을 활용하여 'ref={listWrapperRef}'를 등록해줍니다.
읽어주셔서 감사합니다:)