ABOUT ME

공부좀해보자! 다른사람에게 보여준다기보다 지금은 개발노트

Today
Yesterday
Total
  • Swiper - Cannot read properties of undefined (reading 'autoplay')
    Language/React 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>

    'Language > React' 카테고리의 다른 글

Designed by Tistory.