Skip to content

Commit

Permalink
refactor: remove unnecessary useRef and add comments
Browse files Browse the repository at this point in the history
  • Loading branch information
2wheeh committed Apr 25, 2024
1 parent fb10662 commit 872d9bf
Showing 1 changed file with 50 additions and 50 deletions.
100 changes: 50 additions & 50 deletions ui/src/hooks/common/use-swiper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,55 @@ import { getTouchEventData } from '@/lib/utils/common/get-touch-event-data';
const MIN_SWIPE_REQUIRED = 40; // px

export function useSwiper() {
const [offsetX, setOffsetX, offsetXRef] = useStateRef(0);

const containerRef = useRef<HTMLUListElement>(null);
// onIndicatorClick는 이벤트 등록이 최초 렌더시에 이뤄지므로,
// useRef를 통해 containerWidthRef의 업데이트된 값을 참조하게 해야함
const containerWidthRef = useRef(0);
const minOffsetXRef = useRef(0);
const currentOffsetXRef = useRef(0);
const startXRef = useRef(0);

const [offsetX, setOffsetX, offsetXRef] = useStateRef(0);

const [isSwiping, setIsSwiping] = useState(false);
const [currentIdx, setCurrentIdx] = useState(0);

// 아래 3가지는 onTouchStart 에서 바인딩 된 이후로
// 값이 변하지 않음 => useRef 필요 X
// 오른쪽으로 swipe 하면 slide가 왼쪽으로 넘어감 => offsetX 음수
// 즉 오른쪽으로 swipe 가능한 경계 값
// = 마지막 슬라이드가 오른쪽 끝에서 떨어지는 일은 없음
let minOffsetX: number;
let initialOffsetX: number;
let touchStartX: number;

const onTouchStart = (e: React.TouchEvent<HTMLDivElement> | React.MouseEvent<HTMLDivElement>) => {
setIsSwiping(true);

const containerEl = containerRef.current!;

// set container width
containerWidthRef.current = containerEl.offsetWidth;

// set minOffsetX
minOffsetX = containerWidthRef.current - containerEl.scrollWidth;

initialOffsetX = offsetXRef.current!;
touchStartX = getTouchEventData(e).clientX;

window.addEventListener('touchmove', onTouchMove);
window.addEventListener('touchend', onTouchEnd);
window.addEventListener('mousemove', onTouchMove);
window.addEventListener('mouseup', onTouchEnd);
};

const onTouchMove = (e: globalThis.TouchEvent | globalThis.MouseEvent) => {
const currentX = getTouchEventData(e).clientX;
const diff = startXRef.current - currentX;
let newOffsetX = currentOffsetXRef.current - diff;
const currentTouchX = getTouchEventData(e).clientX;
const swipeDiff = touchStartX - currentTouchX;
let newOffsetX = initialOffsetX - swipeDiff;

// 왼쪽으로 swipe (slide 오른쪽으로 넘김) 시도 시
// offsetX가 0보다 커지는 것을 방지
// = 첫번째 slide 가 왼쪽 끝에서 떨어지는 일은 없음
const maxOffsetX = 0;
const minOffsetX = minOffsetXRef.current;

// TODO: support circular swipe
if (newOffsetX > maxOffsetX) {
newOffsetX = maxOffsetX;
}
Expand All @@ -41,22 +70,23 @@ export function useSwiper() {
};

const onTouchEnd = () => {
const currentOffsetX = currentOffsetXRef.current;
const containerWidth = containerWidthRef.current;
let newOffsetX = offsetXRef.current!;
const diff = currentOffsetX - newOffsetX;
const swipeDiff = initialOffsetX - newOffsetX;

const containerEl = containerRef.current!;
const containerWidth = containerEl.offsetWidth;

// we need to check difference in absolute/positive value (if diff is more than 40px)
if (Math.abs(diff) > MIN_SWIPE_REQUIRED) {
if (diff > 0) {
// swipe to the right if diff is positive
// check difference is bigger than MIN_SWIPE_REQUIRED
if (Math.abs(swipeDiff) > MIN_SWIPE_REQUIRED) {
if (swipeDiff > 0) {
// move to the right slide
newOffsetX = Math.floor(newOffsetX / containerWidth) * containerWidth;
} else {
// swipe to the left if diff is negative
// move to the left slide
newOffsetX = Math.ceil(newOffsetX / containerWidth) * containerWidth;
}
} else {
// remain in the current image
// remain in the current slide
newOffsetX = Math.round(newOffsetX / containerWidth) * containerWidth;
}

Expand All @@ -70,39 +100,9 @@ export function useSwiper() {
window.removeEventListener('mousemove', onTouchMove);
};

const onTouchStart = (e: React.TouchEvent<HTMLDivElement> | React.MouseEvent<HTMLDivElement>) => {
setIsSwiping(true);

currentOffsetXRef.current = offsetXRef.current!;
startXRef.current = getTouchEventData(e).clientX;

const containerEl = containerRef.current;

if (!containerEl) {
return;
}

const containerWidth = containerEl.offsetWidth;

containerWidthRef.current = containerWidth;
minOffsetXRef.current = containerWidth - containerEl.scrollWidth;

window.addEventListener('touchmove', onTouchMove);
window.addEventListener('touchend', onTouchEnd);
window.addEventListener('mousemove', onTouchMove);
window.addEventListener('mouseup', onTouchEnd);
};

const onIndicatorClick = (idx: number) => {
const containerEl = containerRef.current;
if (!containerEl) {
return;
}

const containerWidth = containerEl.offsetWidth;

setCurrentIdx(idx);
setOffsetX(-(containerWidth * idx));
setOffsetX(-(containerWidthRef.current * idx));
};

return {
Expand Down

0 comments on commit 872d9bf

Please sign in to comment.