react로 프론트 개발 중 content를 가로로 스와이프 하는 컴포넌트를 구현하게 되었다.
일반적인 carousel과 유사하지만 이벤트 한 번에 여러 content가 이동하는 게 아니라 사용자가 드래그한 만큼 이동하는 slider에 좀 더 가까운(?) 애니메이션을 보여주어야 했다. 🤔
이를 위해 react-swiper를 이용해 props로 배열(plants)을 받아 아래처럼 출력만 해주는 Slider
컴포넌트를 구현하여 사용하고 있었다.
(SwiperSlide
에 자체 설정된 width를 제거하기 위해 style을 따로 설정했다.)
/* Silder.jsx */
import React from 'react';
import styled from 'styled-components';
import {Swiper, SwiperSlide} from 'swiper/react';
import 'swiper/swiper.scss';
function Slider({plants}) {
return (
<StyledSlider freeMode={true} freeModeMomentum={false} slidesPerView={'auto'}>
{plants.map((plant) => (
<SwiperSlide key={plant.id}>
<div>
<p>아이디: {plant.id}</p>
<p>이름: {plant.name}</p>
<p>종류: {plant.type}</p>
</div>
</SwiperSlide>
))}
</StyledSlider>
);
}
const StyledSlider = styled(Swiper)`
cursor: pointer;
.swiper-slide {
width: max-content !important;
}
`;
export default Slider;
swiper 라이브러리를 사용했지만 프로젝트에서 개발 시 slider라고 지칭했기 때문에 컴포넌트 이름은 Slider
로 설정했다.
plants
의 내용이 업데이트 될 때, 즉 Slider
안 content의 개수가 바뀔 때 정상적으로 스와이프 되지 않는 에러가 발생했다.
개발자 도구로 확인해보니, plants
가 업데이트 되어도 SwiperSlide
의 개수는 처음 받았던 plants
의 length에서 변하지 않아서 에러가 발생한 것 같았다.
stackoverflow에서 react-swiper
컴포넌트 방식으로 특정 option을 추가하는 방법이 몇 개 있길래 시도해봤는데 안 됐다. 😂 (댓글을 보니 다른 사람들도 작동하지 않는 듯)
이렇게 삽질을 하다가..
결국 swiper api 공식 문서를 통해 react 컴포넌트보다는 js 자체로 접근해서 해결했다! 핵심은 다음과 같다.
- swiper 객체에 접근한다.
- content가 바뀔 때마다
swiper.update()
를 실행하여 swiper와 content를 갱신한다.- (추가) 나는 이미 많이 스와이프 한 상황에서 내용이 바뀔 때 처음부터 보여줬으면 좋겠어서
swiper.slideTo
를 통해 처음 요소로 스크롤이 돌아가도록 해 주었다.
코드는 아래와 같다.
/* Silder.jsx */
import React, {useLayoutEffect} from 'react';
import styled from 'styled-components';
import {Swiper, SwiperSlide} from 'swiper/react';
import 'swiper/swiper.scss';
import {isEmptyArr} from '../lib/handler'; // 빈 배열인 지 확인
function Slider({plants}) {
useLayoutEffect(() => {
if (!isEmptyArr(plants)) { // plants가 빈 배열이 아니면
const swiper = document.querySelector('.swiper-container').swiper;
swiper.update();
swiper.slideTo(0);
// update 후 스크롤이 맨 처음 content 위치로 이동
}
}, [plants]);
return (
<StyledSlider freeMode={true} freeModeMomentum={false} slidesPerView={'auto'}>
{plants.map((plant) => (
<SwiperSlide key={plant.id}>
<div>
<p>아이디: {plant.id}</p>
<p>이름: {plant.name}</p>
<p>종류: {plant.type}</p>
</div>
</SwiperSlide>
))}
</StyledSlider>
);
}
const StyledSlider = styled(Swiper)`
cursor: pointer;
.swiper-slide {
width: max-content !important;
}
`
export default Slider;
위 방법을 적용해서 구현한 결과는 여기 키워드 검색 부분에서 확인할 수 있다!
(곧 완성하고 회고할 프로젝트 🏃♀️)
공식 문서의 중요성을 다시금 깨달았다.
라이브러리 사용 시 안 되는 부분이 있으면 구글링으로 빠르게 방법을 찾는 것도 좋겠지만, 다른 이들의 경험에 무조건 의존(?)하기 전에 공식 문서에서 여러 상황에서 가이드를 제공하고 있는 지 꼼꼼히 살펴봐야겠다. 😤
이런 상황이 올 때마다 몇년 전 교수님이 해주신 말씀이 생각난다
#소프트웨어는
#문서가생명이다
피드백은 언제나 환영합니다 ❤