https://myeongsu0257.tistory.com/215#%EC%8B%A4%ED%96%89%ED%99%94%EB%A9%B4-1
React - Carousel설계 ( useRef )
Carousel 도입이유 현재 프로젝트를 진행하면서 페이지가 너무 정적인 경향이 크다고 생각했습니다. 그래서 동적인요소를 추가하고자 했고 그 중에서도 대쉬보드에 Carousel을 도입하여 메인페이지
myeongsu0257.tistory.com
지난번 포스팅에서는 사용자가 버튼을 클릭했을경우에만 슬라이드가 됩니다.
Carousel을 사용하는 유명한 웹사이트들을 보면 사용자가 클릭하지 않아도 자동으로 시간간격에 따라 슬라이드 되는걸 볼 수 있습니다. 따라서 이번에는 일정시간이 지날때마다 Slide되게 해주겠습니다.
설계
먼저 설계입니다. Js에서 일정시간마다 자동으로 어떤 로직을 실행하고 싶을때 setTimeout이라는 함수를 사용합니다.
첫번째 매개변수에 일정시간마다 실행할 함수를 적어줍니다. 저는 이함수에다가 슬라이드 되는 함수를 작성하면됩니다.
시간에는 원하는 시간을 적어주면됩니다.
- setTimeout( 실행할함수, 시간)
위의 setTimeout함수를 useEffect안에 작성해줍니다. 이유는 currentImgIdx라는 state는 사용자가 버튼을 클릭하여 슬라이드를 넘길때 변하는 슬라이드의 인덱스 값인데 이값이 변할때마다 setTimeout을 주었습니다.
useEffect(() => {
slideRef.current.style.transition = "all 0.1s ease-in-out";
slideRef.current.style.transform = `translateX(-${slideRange}px)`;
}, [currentImgIdx]);
useEffect(()=>{
let time = setTimeout(()=>{
if (currentImgIdx == 1) setCurrentImgIdx(currentImgIdx -1);
else if (currentImgIdx == 0) setCurrentImgIdx(currentImgIdx +1);
},5000)
return()=>{
clearInterval(time);
}
},[currentImgIdx])
clean up function으로 useEffect의 return문안에 clearInterval( time ) 을 작성해주었습니다.
즉 useEffect가 동작하기 전에 실행해주는데 왜냐하면 setTimeout()을 쓸 때마다 브라우저 안에 타이머가 하나 생깁니다.
근데 useEffect안에 썻기 때문에 컴포넌트가 mount 될 때마다 실행됩니다.
그래서 자칫 잘못하다가 타이머가 100개 .. 이상 생길 수 도 있습니다.
즉 이런 버그를 방지하기 위해서 기존에 만든 타이머를 싹 제거해야하는데 그럴때 return() => {}안에 작성해줍니다.
안의 코드를 자세히 살펴보면 currentImgIdx가 1일때 0으로 만들어주고 0일때 1로 만들어주었습니다. 그리고 5초마다 실행되도록 해주었습니다.
실행화면
위의 실행화면을 보시면 약간 어색한 부분이 있습니다.
문제점
마지막에서 처음으로 슬라이드
현재는 마지막 슬라이드에서 다시 처음으로 돌아가야할때 오른쪽으로 슬라이드 모션이아닌 왼쪽으로 슬라이드 모션이 되면서 넘어갑니다. 이제 일반적인 사이트를 보시면 한방향(오른쪽)으로만 자동으로 슬라이드 되는데 이렇게 설계하면 됩니다.
해당이미지를 보여주는 배열이 있다고 생각해봅시다. 마지막배열의 인덱스에 도착했을때 마지막요소를 배열 첫번째로 이동시켜주고 첫번째 이후에 요소들을 그 뒤에 붙여주면됩니다.
- 배열의 마지막인덱스에 왔을때 마지막인덱스의 값을 처음으로 할당
- 처음부터 이후에 값들을 두번째부터 할당
하지만 현재 저는 Carousel을 이미지 배열이 아닌 div요소로 표현해주고 있기 때문에 다음에 이미지 배열을 사용하게 된다면 위처럼 구현해보겠습니다.