❗문제상황
프로젝트를 진행하면서 디자인 시안에 따라 스타일을 구현했어야 했는데 온보딩의 캐러셀에서 마지막 슬라이드가 되면 보이던 dots를 없애고 버튼을 띄워야 하는 상황이었다.

캐러셀을 react slick이라는 라이브러리를 사용하여 이미지가 슬라이드되고 dots, skip 버튼은 이미지와 별도로 존재하는 것이었기 때문에 처음 시안을 봤을 땐 구현이 가능할지 확신이 서지 않았었다. 디자이너님께 최대한 구현해 보겠지만 만약 어려운 경우 다시 말씀드리겠다고 했었다. 최대한 구현하고 싶었기에 공식문서를 열심히 찾아봤다.
https://react-slick.neostack.com/docs/api
Neostack
The last react carousel you will ever need
react-slick.neostack.com
공식문서에서 api보단 examples로 어떤 때에 사용하는지 더 제대로 이해할 수 있었다.
해결방법 1. afterChange 사용하기
공식문서에서 찾은 방법은 afterChange라는 옵션을 사용하는 것이었다. afterChange는 말 그대로 캐러셀이 이동한 후에 발동되는 이벤트였고 현재 Index를 인자로 받아올 수 있었다.

const [lastSlide, setLastSlide] = useState(false);
const settings: Settings = {
dots: !lastSlide,
dotsClass: 'dots_custom',
infinite: true,
arrows: false,
autoplay: true,
autoplaySpeed: 5000,
afterChange: (newIndex: number) => setLastSlide(newIndex === 2),
};
현대 index를 받아온 다음 해당 인덱스가 2번(마지막 슬라이드)일 경우 true가 되도록 하였다. 하지만 afterChange는 드래그가 전부 완료되고 난 후에 실행되는 함수라 변경하는 시점이 조금 늦다고 느껴졌다.
그래서 다음으로 시도한 것이 beforeChange 였다.
해결방법 2. beforeChange 사용하기
afterChange가 드래그가 완료된 후라면 beforeChange는 드래그가 시작하는 시점에서 발생하는 이벤트이다.

beforeChange의 경우 oldIndex와 newIndex를 모두 받을 수 있다. oldIndex는 드래그를 시작하는 인덱스이고 newIndex는 드래그해서 보일 슬라이드의 인덱스이다. oldIndex를 기준으로 할 경우, 0번 인덱스에서 0 → 1 → 2로 진행돼서 oldIndex가 1번이지만 0 → 2 → 1로 가면 0번이므로 기준이 애매해지기 때문에 newIndex가 2번일 때를 기준으로 설정하였다.
하지만 문제는 넘어가는 애니메이션이 뚝뚝 끊겨서 매우 보기 안 좋았다는 점이다.

공식문서에서 사용된 예시에서는 정상적으로 작동했는데 내가 뭔가 잘못 써서 그런가? 하고 구글링을 하였더니
https://github.com/akiran/react-slick/issues/1214
beforeChange() breaks fade · Issue #1214 · akiran/react-slick
Sandbox: https://codesandbox.io/s/2j3onlv9rn Removing either beforeChange() or fade restores normal behaviour. But I would want to use both :) NOTE: changing to afterChange() will make slider work,...
github.com
이러한 이슈가 열려있는 것을 확인했다! 많은 사람들이 beforeChange를 사용했을 때 fade가 깨지는 현상을 겪고 있었다. 그리고 여기에서 알려준 해결방법인 setTimeout을 적용해 보았다.
const [lastSlide, setLastSlide] = useState(false);
const settings: Settings = {
dots: !lastSlide,
dotsClass: 'dots_custom',
infinite: true,
arrows: false,
autoplay: true,
autoplaySpeed: 5000,
beforeChange: (_: unknown, newIndex: number) =>
setTimeout(() => {
setLastSlide(newIndex === 2);
}, 350),
};
10 밀리초로 설정 시 여전히 애니메이션이 깨져서 초를 조금씩 늘리면서 350 밀리초 일 때 가장 자연스럽게 넘어가서 해당 밀리초로 설정해 주었다! 이제 처음에 봤던 최종본처럼 자연스럽게 캐러셀이 진행되고 마지막 슬라이드가 되면 dots 대신 버튼이 보이게 된다.
그런데 이 포스팅을 하면서 테스트해보다 드는 생각이 350 밀리초 이후에 state값을 바꾸는 타이밍이 결국 afterChange를 사용한 것과 거의 유사한 것 같다. beforeChange의 애니메이션이 깨지는 것이 해결되지 않았고 setTimeout으로 애니메이션이 거의 완료된 후에 값을 변경하게 되었으니 그게 바로 afterChange 이벤트가 발동되는 타이밍..!
beforeChange 이벤트를 제대로 사용하지 못한 것은 아쉽지만 디자인 시안을 구현할 수 있게 되어 만족스럽다!
'개발 공부 > React' 카테고리의 다른 글
[nextJS] hydration 에러 (0) | 2023.08.13 |
---|---|
[nextJS] 성능 최적화 하기(lighthouse, 빌드 용량 개선) (0) | 2023.07.25 |
[nextJS]일정 시간 이상 걸리는 페이지 이동만 로딩 처리 (0) | 2023.07.23 |
[next + tanstack query] 낙관적 업데이트 적용하기 (0) | 2023.07.22 |
무한스크롤 스크롤 위치 기억하기 (0) | 2023.07.10 |
❗문제상황
프로젝트를 진행하면서 디자인 시안에 따라 스타일을 구현했어야 했는데 온보딩의 캐러셀에서 마지막 슬라이드가 되면 보이던 dots를 없애고 버튼을 띄워야 하는 상황이었다.

캐러셀을 react slick이라는 라이브러리를 사용하여 이미지가 슬라이드되고 dots, skip 버튼은 이미지와 별도로 존재하는 것이었기 때문에 처음 시안을 봤을 땐 구현이 가능할지 확신이 서지 않았었다. 디자이너님께 최대한 구현해 보겠지만 만약 어려운 경우 다시 말씀드리겠다고 했었다. 최대한 구현하고 싶었기에 공식문서를 열심히 찾아봤다.
https://react-slick.neostack.com/docs/api
Neostack
The last react carousel you will ever need
react-slick.neostack.com
공식문서에서 api보단 examples로 어떤 때에 사용하는지 더 제대로 이해할 수 있었다.
해결방법 1. afterChange 사용하기
공식문서에서 찾은 방법은 afterChange라는 옵션을 사용하는 것이었다. afterChange는 말 그대로 캐러셀이 이동한 후에 발동되는 이벤트였고 현재 Index를 인자로 받아올 수 있었다.

const [lastSlide, setLastSlide] = useState(false);
const settings: Settings = {
dots: !lastSlide,
dotsClass: 'dots_custom',
infinite: true,
arrows: false,
autoplay: true,
autoplaySpeed: 5000,
afterChange: (newIndex: number) => setLastSlide(newIndex === 2),
};
현대 index를 받아온 다음 해당 인덱스가 2번(마지막 슬라이드)일 경우 true가 되도록 하였다. 하지만 afterChange는 드래그가 전부 완료되고 난 후에 실행되는 함수라 변경하는 시점이 조금 늦다고 느껴졌다.
그래서 다음으로 시도한 것이 beforeChange 였다.
해결방법 2. beforeChange 사용하기
afterChange가 드래그가 완료된 후라면 beforeChange는 드래그가 시작하는 시점에서 발생하는 이벤트이다.

beforeChange의 경우 oldIndex와 newIndex를 모두 받을 수 있다. oldIndex는 드래그를 시작하는 인덱스이고 newIndex는 드래그해서 보일 슬라이드의 인덱스이다. oldIndex를 기준으로 할 경우, 0번 인덱스에서 0 → 1 → 2로 진행돼서 oldIndex가 1번이지만 0 → 2 → 1로 가면 0번이므로 기준이 애매해지기 때문에 newIndex가 2번일 때를 기준으로 설정하였다.
하지만 문제는 넘어가는 애니메이션이 뚝뚝 끊겨서 매우 보기 안 좋았다는 점이다.

공식문서에서 사용된 예시에서는 정상적으로 작동했는데 내가 뭔가 잘못 써서 그런가? 하고 구글링을 하였더니
https://github.com/akiran/react-slick/issues/1214
beforeChange() breaks fade · Issue #1214 · akiran/react-slick
Sandbox: https://codesandbox.io/s/2j3onlv9rn Removing either beforeChange() or fade restores normal behaviour. But I would want to use both :) NOTE: changing to afterChange() will make slider work,...
github.com
이러한 이슈가 열려있는 것을 확인했다! 많은 사람들이 beforeChange를 사용했을 때 fade가 깨지는 현상을 겪고 있었다. 그리고 여기에서 알려준 해결방법인 setTimeout을 적용해 보았다.
const [lastSlide, setLastSlide] = useState(false);
const settings: Settings = {
dots: !lastSlide,
dotsClass: 'dots_custom',
infinite: true,
arrows: false,
autoplay: true,
autoplaySpeed: 5000,
beforeChange: (_: unknown, newIndex: number) =>
setTimeout(() => {
setLastSlide(newIndex === 2);
}, 350),
};
10 밀리초로 설정 시 여전히 애니메이션이 깨져서 초를 조금씩 늘리면서 350 밀리초 일 때 가장 자연스럽게 넘어가서 해당 밀리초로 설정해 주었다! 이제 처음에 봤던 최종본처럼 자연스럽게 캐러셀이 진행되고 마지막 슬라이드가 되면 dots 대신 버튼이 보이게 된다.
그런데 이 포스팅을 하면서 테스트해보다 드는 생각이 350 밀리초 이후에 state값을 바꾸는 타이밍이 결국 afterChange를 사용한 것과 거의 유사한 것 같다. beforeChange의 애니메이션이 깨지는 것이 해결되지 않았고 setTimeout으로 애니메이션이 거의 완료된 후에 값을 변경하게 되었으니 그게 바로 afterChange 이벤트가 발동되는 타이밍..!
beforeChange 이벤트를 제대로 사용하지 못한 것은 아쉽지만 디자인 시안을 구현할 수 있게 되어 만족스럽다!
'개발 공부 > React' 카테고리의 다른 글
[nextJS] hydration 에러 (0) | 2023.08.13 |
---|---|
[nextJS] 성능 최적화 하기(lighthouse, 빌드 용량 개선) (0) | 2023.07.25 |
[nextJS]일정 시간 이상 걸리는 페이지 이동만 로딩 처리 (0) | 2023.07.23 |
[next + tanstack query] 낙관적 업데이트 적용하기 (0) | 2023.07.22 |
무한스크롤 스크롤 위치 기억하기 (0) | 2023.07.10 |