Language/React
Swiper - Cannot read properties of undefined (reading 'autoplay')
건담아빠
2024. 11. 7. 11:47
React에서 Swiper를 추가하고 autoplay를 시키고 해당 화면에서 나오게 되면 아래와 같은 에러가 발생한다.
Unhandled Runtime Error
TypeError: Cannot read properties of undefined (reading 'autoplay')
원인
GPT 형님께서 말씀하시길 `TypeError: Cannot read properties of undefined (reading 'stop') 오류가 발생하는 경우는 대개 stop 메서드를 호출하려는 객체가 정의되지 않았거나 아직 초기화되지 않았기 때문입니다. 이 오류는 swiperInstance.autoplay.stop() 호출에서 자주 발생할 수 있는데, autoplay 객체가 아직 인스턴스에 초기화되지 않았거나, 다른 이유로 인해 undefined인 상태일 때 그렇습니다.` 라고 하셨고 테스트 진행해보니 그문제가 맞았다.
방법1
컴포넌트가 사라질때 stop 및 destroy하는 코드를 추가하였다.
useEffect(() => {
// 컴포넌트 언마운트 시 Swiper 인스턴스 정리
return () => {
if (swiperInstance) {
if (swiperInstance.autoplay && swiperInstance.autoplay.stop) {
swiperInstance.autoplay.stop();
}
swiperInstance.destroy(true, true);
}
};
}, [swiperInstance]); // swiperInstance가 변경될 때마다 이 effect를 다시 실행
import React, { useEffect, useState } from 'react';
...
SwiperCore.use([Autoplay]);
const RollingNotice = () => {
const [swiperInstance, setSwiperInstance] = useState<SwiperCore | null>(null);
useEffect(() => {
// 컴포넌트 언마운트 시 Swiper 인스턴스 정리
return () => {
if (swiperInstance) {
if (swiperInstance.autoplay && swiperInstance.autoplay.stop) {
swiperInstance.autoplay.stop();
}
swiperInstance.destroy(true, true);
}
};
}, [swiperInstance]); // swiperInstance가 변경될 때마다 이 effect를 다시 실행
...
return (
<div className={cx('wrap-rolling-notices')}>
<Swiper
onSwiper={setSwiperInstance} // Swiper 인스턴스를 상태에 저장
modules={[Autoplay]}
...
>
{items.map((item, index) => (
<SwiperSlide ...>
...
</SwiperSlide>
))}
</Swiper>
</div>
);
};
export default RollingNotice;
방법2
Swiper에서 onBeforeDestroy을 활용하는것이다.
<Swiper
onBeforeDestroy={(swiper) => {
// Ensure autoplay is stopped before component unmounts
if (swiper.autoplay) {
swiper.autoplay.stop();
}
}}
...
>
<Swiper
onBeforeDestroy={(swiper) => {
// Ensure autoplay is stopped before component unmounts
if (swiper.autoplay) {
swiper.autoplay.stop();
}
}}
...
>
{items &&
items.map((item, idx) => (
<SwiperSlide ...>
...
</SwiperSlide>
))}
</Swiper>
입맛에 맞게 쓰면 되겠지만 `방법1`은 리액트에서 컴포턴트가 사라질때 컨트롤 하는것이고, `방법2`는 Swiper 컴포넌트에서 제공되는 함수를 활용 하는것이다.
필자는 `방법2`가 소스 가독성으로도 좋아서 2번 방법으로 적용하였다.
추가적인 오류
swiper.params.autoplay.reverseDirection 이부분에서 에러 발생
reverseDirection: false 옵션 추가
<Swiper
...
autoplay={{
delay: 3000,
disableOnInteraction: false,
reverseDirection: false
}}
...
>
...
</Swiper>