React-slick) 인덱스 상태관리 (beforeChange, afterChange)

리오·2023년 5월 29일
0

Front End

목록 보기
6/10
post-thumbnail

들어가며

회사에서 Vue로 작성된 레거시 코드를 React로 마이그레이션 작업을 하면서, 슬라이더 컴포넌트를 만들어야 하는 상황이 생겼습니다.
기존 레거시 코드는 vue-slider를 사용하고 있었는데, React 환경에 맞는 라이브러리를 변경해야하는 상황이었습니다. 따라서 react-slick을 도입했고, 기존의 기능과 디자인을 재현하기 위해 노력했던 흔적을 정리합니다.

요구사항

블록 넘버 배열의 각 넘버를 슬라이더의 요소에 하나씩 표시하고, 슬라이더에서 메인이 되는 요소의 인덱스를 상태를 통해서 관리합니다.
메인이 되는 요소에는 투명도와 크기를 변경해주어 메인이 되는 요소임을 표시해줍니다.

react-slick으로 슬라이더 구현

JQuery 없이 사용하기

React-slick 라이브러리 자체에는 JQuery에 대한 의존성이 없습니다. 다만 slick의 내장 css에는 JQuery에 대한 의존성이 있었습니다.

//⛔️jQuery 의존성 존재
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";

이번 프로젝트에서 JQuery에 대한 의존성 추가를 지양했기 때문에, 아래 링크에서 css 파일을 따로 가져온 후, style 디렉토리에 넣어주었습니다. 그리고 코드의 font 등 파일을 가져오는 코드는 주석처리하였습니다.

https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick-theme.css
https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick.css

그리고 슬라이더 컴포넌트에서 해당 css 파일을 import 해주었습니다.

import '../styles/slick-theme.scss';
import '../styles/slick.scss';

index 상태관리

blockList에 담긴 각각의 번호를 슬라이더에 표시해줍니다. 이때 슬라이더에서 가장 왼쪽에 표시되는 블록의 index를 currentIndex라는 상태로 관리해줍니다.

	const [currentIndex, setCurrentIndex] = useState(0);
	const blockList = [1, 2, 3, 4, 5];

가장 왼쪽에 표시되는 블록에는 'active' 클래스를 부여해서 css 속성을 적용해줍니다.

 ${currentIndex === index && styles.active}

setting 선언

react slick을 사용하는 경우에는 setting을 정의해주어 Slider의 props로 전달해줍니다.
공식 홈페이지에 나와있는 기본 형태는 다음과 같습니다.

import React, { Component } from "react";
import Slider from "react-slick";

export default function SimpleSlider(){
    const settings = {
      dots: true,
      infinite: true,
      speed: 500,
      slidesToShow: 1,
      slidesToScroll: 1
    };
    return (
      <div>
        <h2> Single Item</h2>
        <Slider {...settings}>
          <div>
            <h3>1</h3>
          </div>
          <div>
            <h3>2</h3>
          </div>
          <div>
            <h3>3</h3>
          </div>
          <div>
            <h3>4</h3>
          </div>
          <div>
            <h3>5</h3>
          </div>
          <div>
            <h3>6</h3>
          </div>
        </Slider>
      </div>
    );
}
  • dots: 슬라이드 하단에 점(.)을 표시할 지 정하는 boolean 값
  • infinite: 슬라이드의 마지막 요소를 표시한 이후에 다시 첫 번째 요소를 표시할 지 정하는 boolean 값
  • speed: 슬라이드 넘어가는 속도 (ms)
  • slidesToShow: 슬라이드에서 한 프레임에 몇 개의 요소를 보여줄지 정하는 정수(int) 값
  • slidesToScroll: 한번개 몇 개의 요소가 넘어갈지 정하는 정수값

beforeChange

저는 셋팅을 요구사항에 맞게 다음과 같이 변경하였습니다.

const defaultSetting = {
	dots: true,
	infinite: true,
	speed: 500,
};
export default function BlockSlider() {
	const [currentIndex, setCurrentIndex] = useState(0);
	const blockList = [1, 2, 3, 4, 5];
	const settings = {
		...defaultSetting,
		slidesToShow: 3,
		slidesToScroll: 1,
		beforeChange: (_, newIndex) => {
			setCurrentIndex(newIndex);
		},
	};
 }

setting의 마지막 속성인 beforeChange는 슬라이더의 인덱스가 변경되기 직전에 호출되는 콜백함수입니다.
이 콜백함수의 첫번째 인자는 oldIndex(변경되기 이전의 인덱스) 두번째 인자는 newIndex(변경된 이후의 인덱스) 입니다.
이전 인덱스 정보는 사용할 필요가 없어서 첫번째 인자에 '_'를 주었습니다.

전체 코드를 보면 다음과 같습니다

import React, { useState } from 'react';
import Slider from 'react-slick';
import '../styles/slick-theme.scss';
import '../styles/slick.scss';
import styles from '../styles/BlockSlider.module.scss';

const defaultSetting = {
	dots: true,
	infinite: true,
	speed: 500,
};
export default function BlockSlider() {
	const [currentIndex, setCurrentIndex] = useState(0);
	const blockList = [1, 2, 3, 4, 5];
	const settings = {
		...defaultSetting,
		slidesToShow: 3,
		slidesToScroll: 1,
		beforeChange: (_, newIndex) => {
			setCurrentIndex(newIndex);
		},
	};

	return (
		<div className={styles.container}>
			<h2> Single Item</h2>
			<Slider {...settings} className={styles.slider}>
				{blockList.map((blockNumber, index) => (
					<div key={index} className={styles.block}>
						<div
							className={`${styles.circle} ${
								currentIndex === index && styles.active
							}`}
						>
							<p className={styles.content}>{blockNumber}</p>
						</div>
					</div>
				))}
			</Slider>
		</div>
	);
}

코드에서 보면 map의 콜백함수에서 index가 현재 표시되고 있는 currentIndex와 일치할 때, active 클래스를 주어서 css를 변경합니다.
다음 코드의 결과입니다.

⚠️ afterChange

afterChange는 슬라이더의 인덱스가 변경된 직후에 실행되는 콜백함수입니다.
beforeChange 대신에 afterChange를 사용해서 코드를 작성해보았습니다.

	const settings = {
		...defaultSetting,
		slidesToShow: 3,
		slidesToScroll: 1,
		afterChange: (newIndex) => {
			setCurrentIndex(newIndex);
		},
	};

이렇게 작성했을 때, 다음과 같은 결과가 나타났습니다

보시다시피 슬라이드의 요소가 변경되고 난 후에야 currentIndex의 상태변경이 이루어지기 때문에, css 적용되는 데 딜레이가 발생하고 있습니다.

단순히 현재 활성화된 요소의 인덱스 정보만 알면 되는 경우에는 afterChange를 사용해도 될 것 같습니다.
하지만 활성화된 요소의 css 변경이 슬라이드가 넘어가는 애니메이션과 동시에 적용되어야 할 때에는 beforeChange가 더 적합해보입니다.

마치며

프로젝트를 하면서 불필요한 의존성은 늘리지 않으려고 하고 있습니다만, 더 깔끔한 코드와 디자인을 자랑하는 라이브러리의 유혹에 넘어가지 않기란 쉽지 않은 것 같습니다. 특히나 신입이고, 혼자서 프로젝트를 하는 입장에서 기한을 맞추기 위해 어쩔 수 없이 라이브러리를 사용하게 되는 것 같습니다. 라이브러리를 사용하기 전에 라이브러리의 공식 문서와 예제를 꼼꼼히 확인하여 더 효율적으로 사용하는 것이 중요할 것 같습니다.

출처

react-slick 공식문서

profile
오늘도 승승장구를 위해 연습 중

0개의 댓글