본문 바로가기

리액트

React 캐로셀

캐로셀 라이브러리 없이 구현하기

구조 파악하기

  • 기본 구조는 가로로 쭉 나열이 되어 있어야 한다.
  • 처음에 쭉 나열이 되어 있으면 브라우저에 스크롤? x가 생길 것이다.
  • 이 스크롤을 css로 overflow을 hidden으로 설정 해준다.
  • 이제 버튼을 눌렀을 떄 앞으로, 뒤로 가게 하면 되는데 이떄 css에 transform: `translateX()'을 써준다.

구현하기

많은 곳에서 쓰이니깐 커스텀 훅으로 만들어 주었다.


import React, { useCallback, useEffect, useState } from 'react'

const UsePreBtn = (data) => {
  const [index, setIndex] = useState(0)
  const [cardsPerView, setCardsPerView] = useState(5)

  const handleNextClick = useCallback(() => {
    setIndex((prev) => (prev + 1) % Math.ceil(data.length / cardsPerView))
  }, [data.length, cardsPerView])

  const handlePrevClick = useCallback(() => {
    setIndex(
      (prev) =>
        (prev - 1 + Math.ceil(data.length / cardsPerView)) %
        Math.ceil(data.length / cardsPerView)
    )
  }, [data.length, cardsPerView])

  const updateCardsPerView = useCallback(() => {
    if (window.innerWidth > 1200) setCardsPerView(5)
    if (window.innerWidth > 1000) setCardsPerView(3)
  }, [])

  useEffect(() => {
    updateCardsPerView()

    window.addEventListener('resize', updateCardsPerView)
    return () => {
      window.removeEventListener('resize', updateCardsPerView)
    }
  }, [updateCardsPerView])
  return { handlePrevClick, handleNextClick, cardsPerView, index }
}

export default UsePreBtn

코드 하나씩 뜯어보기

  • state로 현재 인덱스와 화면에 보여줄 카드 수를 관리합니다. 초기값으로 `index`는 0, `cardsPerView`는 5로 설정되어 있습니다.

    
          const [index, setIndex] = useState(0)
          const [cardsPerView, setCardsPerView] = useState(5)
    
  • `useCallback` hook은 함수를 다른 곳에서 재생성하지 않도록 하는 역할 `handleNextClick`은 다음 페이지로 이동하는 로직입니다. `Math.ceil`을 사용해 전체 페이지 수를 계산하고, 현재 인덱스를 다음으로 넘기는 로직을 구현했습니다. 예) 데이터 길이가 10, 한 페이지에 5개를 보여준다면, 전체 페이지 수는 2.

    
          const handleNextClick = useCallback(() => {
            setIndex((prev) => (prev + 1) % Math.ceil(data.length / cardsPerView))
          }, [data.length, cardsPerView])
    
  • `handlePrevClick`은 이전 페이지로 이동하는 로직입니다. 현재 인덱스에서 1을 빼고 음수가 되지 않도록 전체 페이지 수를 더해 % 연산으로 순환 구조를 만듭니다.

    
          const handlePrevClick = useCallback(() => {
            setIndex(
              (prev) =>
                (prev - 1 + Math.ceil(data.length / cardsPerView)) %
                Math.ceil(data.length / cardsPerView)
            )
          }, [data.length, cardsPerView])
    
  • `innerWidth`로 브라우저 가로 크기를 확인해 조건에 맞게 화면에 보여줄 카드 수를 변경합니다. 이를 통해 반응형 디자인을 간단히 구현할 수 있습니다.

    
          const updateCardsPerView = useCallback(() => {
            if (window.innerWidth > 1200) setCardsPerView(5)
            else if (window.innerWidth > 1000) setCardsPerView(3)
          }, [])
    
  • `useEffect`로 창 크기가 변경될 때마다 `updateCardsPerView`를 실행합니다. 최적화를 위해 이벤트 리스너를 등록/해제합니다.

    
          useEffect(() => {
            updateCardsPerView()
    
            window.addEventListener('resize', updateCardsPerView)
            return () => {
              window.removeEventListener('resize', updateCardsPerView)
            }
          }, [updateCardsPerView])
    

연결하기

음수 값은 CSS에서 "왼쪽" 방향으로 이동을 의미하므로, 슬라이드 기능을 만들 때 다음 콘텐츠를 왼쪽으로 밀어내면서 현재 콘텐츠를 교체하는 효과를 줍니다.


    transform: `translateX(-${index * (100 / cardsPerView)}%)`,

'리액트' 카테고리의 다른 글

React  (0) 2025.01.07
React-player 라이브러리  (0) 2024.12.31
React Potal Modal 구현하기  (3) 2024.12.31
React scroll시 css 변경하기  (0) 2024.12.31
React 커스텀 Hook, await와 axios.all 활용법  (4) 2024.12.28