본문 바로가기
react

Swiper Navigator(화살표) 바깥으로 빼기

by HomieKim 2022. 7. 21.

프로젝트 KKu-Woon을 진행하며 유저 리스트를 carousel 형식으로 구현해야 상황이 있었습니다.

구현하려는 ui

프로젝트 기간이 여유롭지 않고, 캐러셀은 라이브러리로 잘 만들어져 있기 때문에 오픈 소스를 사용하여 구현하기로 결정하였습니다.

고려한 라이브러리는 "react-slick" 과 "swiper" 두가지 라이브러리를 고려하였습니다. 그 중 swipe를 사용하여 해당 ui를 구현하였고 구현하면서 발생한 에러와 해결방법을 공유합니다.


✔ Swiper를 사용한 이유?

  • 예전에 강좌를 들으면서 react-slick을 한번 사용해 보았고 새로운 라이브러리 사용 방법을 공부하고 싶었음
  • react-slick 경우 @types 파일이 있었지만 js 기반으로 구현되어 있고 swiper는 typescript로 구현 되어있음
  • swiper 가 github star, npm download 수가 더 많았음

결론 부터 말하자면 저렇게 navigator 바깥에 있는 ui는 그냥 react-slick을 쓰는 게 더 좋을지도 모르겠다.

 

 swiper 같은 경우는 navigator가 캐러셀 안에 즉, swipe-wrapper 안에 들어있어서 css를 커스텀하는 방식으로는 화살표가 사라져 바깥으로 사라지는 이슈가 있었습니다.

✔ 해결방법?

  •  해결 방법을 구글에 찾아 봤는데 여기서 고생을 한게 구글에 있는 대부분의 해결 방법이 swiper 6버전을 기준으로 작성되어있고 최신버전인 8버전에서는 정상적으로 동작 하지 않는 이슈가 있었음
  • 버전을 낮추는 방법도 시도 했지만 swiper에서 낮은 버전의 api를 지원하지 않을 수 도 있다는 글을 보았음
  • useRef를 사용해서 button에 ref를 달아서 조작하는 방법을 시도 했는데 typescript 환경에서 정상적으로 동작되지 않음 (ref가 null이라고 나오거나 type error 발생)
  • 최종적으로 해결 방법을 찾은 곳은https://github.com/nolimits4web/swiper/issues/3855#issuecomment-1010689372
 

[swiper/react] Custom navigation/pagination components using React refs not working/possible? · Issue #3855 · nolimits4web/swi

Swiper Version: 6.2.0 Platform/Target and Browser Versions: All Also posten on Stackoverflow: Swiper React | How to create custom navigation/pagination components using React refs? What you did con...

github.com

이 방법을 기반으로 Swiper에 state를 달아서 사용하는 방법으로 해결

 

✔ Code

import React, { useState } from 'react';
import { Swiper, SwiperSlide } from 'swiper/react';
import { SwiperWrapper, Wrapper } from './carousel.style';
import { userDummy } from 'dummy';
import CarouselItem from './carousel-item';
import { ReactComponent as RightArrow } from '@assets/icons/right-arrow.svg';
import { ReactComponent as LeftArrow } from '@assets/icons/left-arrow.svg';
const UserCarousel = () => {
  const userData = userDummy;
  const [swiper, setSwiper] = useState<any>();
  const [reachingEnd, setReachingEnd] = useState<boolean>(false);
  const [reachingFirst, setReachingFirst] = useState<boolean>(true);
  return (
    <Wrapper>
      <h2>운동 현황보기</h2>
      <SwiperWrapper>
        <button onClick={() => swiper?.slidePrev()} disabled={reachingFirst}>
          <LeftArrow stroke={reachingFirst ? '#D4D2D9' : '#6732FF'} />
        </button>
        <Swiper
          slidesPerView={4}
          slidesPerGroup={4}
          onBeforeInit={swipper => setSwiper(swipper)}
          onSlideChange={e => {
            e.isEnd ? setReachingEnd(true) : setReachingEnd(false);
            e.isBeginning ? setReachingFirst(true) : setReachingFirst(false);
          }}
        >
          {userData.map(v => (
            <SwiperSlide key={v.id}>
              <CarouselItem nickname={v.nickname} url={v.imageUrl} />
            </SwiperSlide>
          ))}
        </Swiper>
        <button onClick={() => swiper?.slideNext()} disabled={reachingEnd}>
          <RightArrow stroke={reachingEnd ? '#D4D2D9' : '#6732FF'} />
        </button>
      </SwiperWrapper>
    </Wrapper>
  );
};

export default UserCarousel;

css code:

import styled from 'styled-components';

export const Wrapper = styled.section`
  padding: 30px 0px 0px 0px;
  & h2 {
    margin-left: 20px;
    font-weight: 700;
    font-size: 18px;
  }
`;

export const SwiperWrapper = styled.div`
  position: absolute;
  width: 100%;
  margin-top: 12px;
  display: flex;
  & button {
    background: transparent;
  }
  .swiper {
    text-align: center;
  }
`;

export const ItemWrapper = styled.div`
  & img {
    width: 50px;
    height: 50px;
    border-radius: 50%;
  }
`;

 해결해서 다행이지만 그냥 react-slick 쓸걸 그랬다. 공식문서를 확인해 보면 내가 구현하려는 ui는 react-slick에서 기본 제공하는 ui 와 더 유사한듯

https://react-slick.neostack.com/docs/example/pause-on-hover

 

Neostack

The last react carousel you will ever need

react-slick.neostack.com

라이브러리 사용하는 것도 무작정 갖다 쓰는게 아니라 구현하려는 ui와 구현 방법을 먼저 고려하고 선택해야 함을 배움

댓글