React를 사용하여 자동 슬라이드 쇼를 만드는 방법

This article was originally published on Tinloof.


최종 결과
본 논문에서, 우리는 React를 사용하여 슬라이드를 자동으로 재생하는 것을 구축할 것이다.
본문은 두 부분으로 나뉜다.
  • 노하우
  • 기능
  • 다음은 최종 결과(Codepen 링크 here과 Codesandbox 링크 here)입니다.

    비결


    슬라이드 구성 요소는
  • 슬라이드 쇼
  • 슬라이딩 레일
  • 슬라이드
  • 다음은 구조를 시각화하는 도식입니다.

    빨간색 상자에 표시된 내용(컨테이너 슬라이드)을 볼 수 있습니다.
    몇 초 후 컨테이너 슬라이드 블록이 왼쪽으로 이동하여 다음 컨테이너 슬라이드를 표시합니다.

    몇 초 후에 용기 슬라이드 슬라이더가 다시 이동하여 사용자에게 노란색 용기 슬라이드를 보일 것이라고 상상할 수 있다.
    몇 초 후, 용기 슬라이더는 원래의 위치로 돌아갈 것이며, 우리는 다시 파란색 용기 슬라이더를 볼 것이다.
    잠깐만요.
    다음은 해당 태그입니다.
    function Slideshow() {
      return (
        <div className="slideshow">
          <div className="slideshowSlider">
            <div className="slide"></div>
          </div>
        </div>
      );
    }
    

    1단계: 컬러 슬라이드 쇼


    앞의 마커를 사용하여 몇 개의 컬러 슬라이드를 보여 드리겠습니다.
    const colors = ["#0088FE", "#00C49F", "#FFBB28"];
    
    function Slideshow() {
      return (
        <div className="slideshow">
          <div className="slideshowSlider">
            {colors.map((backgroundColor, index) => (
              <div className="slide" key={index} style={{ backgroundColor }}/>
            ))}
          </div>
        </div>
      );
    }
    
    

    2단계: 스타일


    먼저 상위 컨테이너 슬라이드의 스타일을 설계합니다.
    /* Slideshow */
    
    .slideshow {
      margin: 0 auto;
      overflow: hidden;
      max-width: 500px;
    }
    
    우리는 margin: 0 auto을 사용하여 가운데에 놓고 max-width을 설정하며 overflow:hidden을 사용하여 원소 상자 밖의 내용을 보이지 않게 한다.
    이제 슬라이드를 살펴보겠습니다.
    /* Slideshow */
    
    .slideshow {
      margin: 0 auto;
      overflow: hidden;
      max-width: 500px;
    }
    
    .slide {
      height: 400px;
      width: 100%;
      border-radius: 40px;
    }
    
    우리는 다음과 같은 것을 얻었다.
    장의 슬라이드 중첩
    우리는 슬라이드가 한 장 한 장 다른 장 위에 놓여 있는 것을 원하지 않지만, 우리는 슬라이드가 한 장 한 장 붙어 있기를 바란다.
    이를 위해 display: inline-block을 설정합니다. 기본적으로 divdisplay:block으로 설정되어 있어서 새로운 줄에서 시작합니다.
    /* Slideshow */
    
    .slideshow {
      margin: 0 auto;
      overflow: hidden;
      max-width: 500px;
    }
    
    .slide {
      display: inline-block;
    
      height: 400px;
      width: 100%;
      border-radius: 40px;
    }
    
    우리는 다음과 같은 것을 얻었다.
    은 변화가 크지 않다
    큰 변화가 없고 display:block이 있는 것 같다. div이 용기에 공간이 없을 때 다음 줄로 줄을 바꾸기 때문이다.우리의 슬라이드는 슬라이드 폭의 100%를 차지하기 때문에 용기에 공간이 없다.
    슬라이드 컨테이너에 white-space: nowrap을 사용할 예정이므로 다음 줄로 행이 바뀌지 않습니다.
    /* Slideshow */
    
    .slideshow {
      margin: 0 auto;
      overflow: hidden;
      max-width: 500px;
    }
    
    .slideshowSlider {
      white-space: nowrap;
    }
    
    .slide {
      display: inline-block;
    
      height: 400px;
      width: 100%;
      border-radius: 40px;
    }
    
    우리는 다음과 같은 것을 얻었다.
    다음 행은 포장하지 않음
    우리는 더 이상 divs를 다음 생산 라인으로 포장하지 않는다.

    3단계:버튼 만들기


    현재 우리는 색 용기의 구조를 가지고 있으며, 그것들 아래에 단추 (점) 를 추가할 것이다.
    배열을 다시 매핑하고 각 배열 요소에 점을 추가합니다.
    const colors = ["#0088FE", "#00C49F", "#FFBB28"];
    
    function Slideshow() {
      return (
        <div className="slideshow">
          <div className="slideshowSlider">
            {colors.map((backgroundColor, index) => (
              <div
                className="slide"
                key={index}
                style={{ backgroundColor }}
              ></div>
            ))}
          </div>
    
          <div className="slideshowDots">
            {colors.map((_, idx) => (
              <div key={idx} className="slideshowDot"></div>
            ))}
          </div>
        </div>
      );
    }
    
    버튼을 설계해 보겠습니다.
    /* Slideshow */
    
    .slideshow {
      margin: 0 auto;
      overflow: hidden;
      max-width: 500px;
    }
    
    .slideshowSlider {
      white-space: nowrap;
    }
    
    .slide {
      display: inline-block;
    
      height: 400px;
      width: 100%;
      border-radius: 40px;
    }
    
    /* Buttons */
    
    .slideshowDots {
      text-align: center;
    }
    
    .slideshowDot {
      display: inline-block;
      height: 20px;
      width: 20px;
      border-radius: 50%;
    
      cursor: pointer;
      margin: 15px 7px 0px;
    
      background-color: #c4c4c4;
    }
    
    우리는 다음과 같은 것을 얻었다.

    색상 컨테이너와 버튼(점) 준비 완료
    우리는 이미 구조와 조형을 완성했다.이제 슬라이드의 기능을 살펴보겠습니다.

    기능


    위의 스케치에서 보시면, 슬라이드쇼 슬라이더의 위치를 왼쪽으로 옮겨서, 아버지 슬라이드 div에 다른 색 용기를 표시합니다.
    다음 파란색 컨테이너가 슬라이더를 이동하면서 왼쪽으로 이동하는 방법에 주의하십시오.
    슬라이드 기능 뒷면의 논리
    이를 위해 transform: translate3d(또는 transform: translate)을 사용하겠습니다.
    우리가 여기서 주로 하고 싶은 것은 인덱스가 0일 때 슬라이더의 위치를 0%, 인덱스가 1일 때 100%, 인덱스가 2일 때 -200% 이동하는 것이다.
    현재 표시된 색인을 추적하기 위해useState를 사용하고 0으로 초기화합니다.
    const colors = ["#0088FE", "#00C49F", "#FFBB28"];
    
    function Slideshow() {
      const [index, setIndex] = React.useState(0);
    
      return (
        <div className="slideshow">
          <div
            className="slideshowSlider"
            style={{ transform: `translate3d(${-index * 100}%, 0, 0)` }}
          >
            {colors.map((backgroundColor, index) => (
              <div
                className="slide"
                key={index}
                style={{ backgroundColor }}
              ></div>
            ))}
          </div>
    
          <div className="slideshowDots">
            {colors.map((_, idx) => (
              <div key={idx} className="slideshowDot"></div>
            ))}
          </div>
        </div>
      );
    }
    
    슬라이드를 자동으로 재생하기 위해서, 우리는 setTimeout을 사용하여 2.5초에 한 번씩 색인을 변경합니다.
    이것은 side effect이기 때문에, 우리가 이렇게 하는 것은 유용하다.
    인덱스가 바뀔 때마다 이 동작을 실행하기를 원하기 때문에,useEffect에 전달되는 의존 항목 그룹에 인덱스를 넣습니다.
    const colors = ["#0088FE", "#00C49F", "#FFBB28"];
    const delay = 2500;
    
    function Slideshow() {
      const [index, setIndex] = React.useState(0);
    
      React.useEffect(() => {
        setTimeout(
          () =>
            setIndex((prevIndex) =>
              prevIndex === colors.length - 1 ? 0 : prevIndex + 1
            ),
          delay
        );
    
        return () => {};
      }, [index]);
    
      return (
        <div className="slideshow">
          <div
            className="slideshowSlider"
            style={{ transform: `translate3d(${-index * 100}%, 0, 0)` }}
          >
            {colors.map((backgroundColor, index) => (
              <div
                className="slide"
                key={index}
                style={{ backgroundColor }}
              ></div>
            ))}
          </div>
    
          <div className="slideshowDots">
            {colors.map((_, idx) => (
              <div key={idx} className="slideshowDot"></div>
            ))}
          </div>
        </div>
      );
    }
    
    
    2500밀리초(2.5초)마다 setIndex 함수를 호출합니다.현재 인덱스가 그룹의 길이를 1로 줄였는지 먼저 검사합니다. 그러면 다음 인덱스로 이동할지 처음부터 시작할지 알 수 있습니다.
    예를 들어, 만약 우리가 인덱스 0에 있다면, 이것은 그룹의 길이를 1로 줄이는 것이 아니라, 인덱스를 1로 업데이트할 것이다.
    그러나 만약 우리가 인덱스 2에 있다면, 이것은 그룹의 길이를 1로 줄이는 것과 같다. (3-1=2) 인덱스는 0으로 업데이트될 것이다.
    우리는 다음과 같은 것을 얻었다.

    슬라이드 쇼 진행 중
    보다 매끄러운 전환을 원하므로 CSS로 돌아가서 슬라이드 쇼 슬라이더에 transition을 추가하겠습니다.
    /* Slideshow */
    
    .slideshow {
      margin: 0 auto;
      overflow: hidden;
      max-width: 500px;
    }
    
    .slideshowSlider {
      white-space: nowrap;
      transition: ease 1000ms;
    }
    
    .slide {
      display: inline-block;
    
      height: 400px;
      width: 100%;
      border-radius: 40px;
    }
    
    /* Buttons */
    
    .slideshowDots {
      text-align: center;
    }
    
    .slideshowDot {
      display: inline-block;
      height: 20px;
      width: 20px;
      border-radius: 50%;
    
      cursor: pointer;
      margin: 15px 7px 0px;
    
      background-color: #c4c4c4;
    }
    
    이제 더 좋아졌어요.
    슬라이드 애니메이션과 transition의 장점
    슬라이드는 정상적으로 상영되지만, 단추는 활성 슬라이드를 반영하지 않습니다.
    지금까지 우리의 모든 단추는 회색이었다.현재 슬라이드 색인 (index 상태값) 에 대응하는 단추를 보라색으로 칠하는 'active' 를 추가합니다.
    색상을 매핑할 때 슬라이드의 인덱스가 점 인덱스와 같은지 확인합니다. 이 경우 색상의 변화를 반영하기 위해 추가 클래스 이름을 활성화해야 합니다.
    const colors = ["#0088FE", "#00C49F", "#FFBB28"];
    const delay = 2500;
    
    function Slideshow() {
      const [index, setIndex] = React.useState(0);
    
      React.useEffect(() => {
        setTimeout(
          () =>
            setIndex((prevIndex) =>
              prevIndex === colors.length - 1 ? 0 : prevIndex + 1
            ),
          delay
        );
    
        return () => {};
      }, [index]);
    
      return (
        <div className="slideshow">
          <div
            className="slideshowSlider"
            style={{ transform: `translate3d(${-index * 100}%, 0, 0)` }}
          >
            {colors.map((backgroundColor, index) => (
              <div
                className="slide"
                key={index}
                style={{ backgroundColor }}
              ></div>
            ))}
          </div>
    
          <div className="slideshowDots">
            {colors.map((_, idx) => (
              <div
                key={idx}
                className={`slideshowDot${index === idx ? " active" : ""}`}
              ></div>
            ))}
          </div>
        </div>
      );
    }
    
    
    이제 활동 클래스 이름에 해당하는 스타일을 추가합니다.
    /* Slideshow */
    
    .slideshow {
      margin: 0 auto;
      overflow: hidden;
      max-width: 500px;
    }
    
    .slideshowSlider {
      white-space: nowrap;
      transition: ease 1000ms;
    }
    
    .slide {
      display: inline-block;
    
      height: 400px;
      width: 100%;
      border-radius: 40px;
    }
    
    /* Buttons */
    
    .slideshowDots {
      text-align: center;
    }
    
    .slideshowDot {
      display: inline-block;
      height: 20px;
      width: 20px;
      border-radius: 50%;
    
      cursor: pointer;
      margin: 15px 7px 0px;
    
      background-color: #c4c4c4;
    }
    
    .slideshowDot.active {
      background-color: #6a0dad;
    }
    
    이제 슬라이드의 변경 사항이 반영된 버튼:

    버튼은 지금 확실히 이러한 변화를 반영하고 있다
    이제 첫 번째 점을 클릭하면 파란색 용기가 표시되고, 두 번째 점을 클릭하면 녹색 용기가 표시되며, 세 번째 점을 클릭하면 노란색 용기가 표시됩니다.
    이렇게 하려면 슬라이드의 인덱스를 버튼의 인덱스와 동일하게 변경합니다.
    const colors = ["#0088FE", "#00C49F", "#FFBB28"];
    const delay = 2500;
    
    function Slideshow() {
      const [index, setIndex] = React.useState(0);
    
      React.useEffect(() => {
        setTimeout(
          () =>
            setIndex((prevIndex) =>
              prevIndex === colors.length - 1 ? 0 : prevIndex + 1
            ),
          delay
        );
    
        return () => {};
      }, [index]);
    
      return (
        <div className="slideshow">
          <div
            className="slideshowSlider"
            style={{ transform: `translate3d(${-index * 100}%, 0, 0)` }}
          >
            {colors.map((backgroundColor, index) => (
              <div
                className="slide"
                key={index}
                style={{ backgroundColor }}
              ></div>
            ))}
          </div>
    
          <div className="slideshowDots">
            {colors.map((_, idx) => (
              <div
                key={idx}
                className={`slideshowDot${index === idx ? " active" : ""}`}
                onClick={() => {
                  setIndex(idx);
                }}
              ></div>
            ))}
          </div>
        </div>
      );
    }
    
    
    그러나 이것은 효과적이다. 왜냐하면 우리는 setTimeout을 제거하지 않았기 때문이다. 여러 번의 클릭을 통해 우리는 타이머의 값을 왜곡했다.

    타이머 값이 지워지지 않았습니다.
    이러한 상황을 피하기 위해서 우리는 setTimeout 방법으로 clearTimeout을 제거할 것이다.setTimeout()에서 반환된 ID 값은 clearTimeout()의 매개변수로 사용됩니다.
    이러한 GIF의 상황을 피하기 위해 변수에 저장하고 clearTimeout()을 사용하여 0부터 시간을 재겠습니다.
    변수를 저장하기 위해 useRef을 사용하여 객체의 값이 객체의 current 속성을 통해 액세스되는 객체를 만들었습니다.
    const colors = ["#0088FE", "#00C49F", "#FFBB28"];
    const delay = 2500;
    
    function Slideshow() {
      const [index, setIndex] = React.useState(0);
      const timeoutRef = React.useRef(null);
    
      React.useEffect(() => {
        timeoutRef.current = setTimeout(
          () =>
            setIndex((prevIndex) =>
              prevIndex === colors.length - 1 ? 0 : prevIndex + 1
            ),
          delay
        );
    
        return () => {};
      }, [index]);
    
      return (
        <div className="slideshow">
          <div
            className="slideshowSlider"
            style={{ transform: `translate3d(${-index * 100}%, 0, 0)` }}
          >
            {colors.map((backgroundColor, index) => (
              <div
                className="slide"
                key={index}
                style={{ backgroundColor }}
              ></div>
            ))}
          </div>
    
          <div className="slideshowDots">
            {colors.map((_, idx) => (
              <div
                key={idx}
                className={`slideshowDot${index === idx ? " active" : ""}`}
                onClick={() => {
                  setIndex(idx);
                }}
              ></div>
            ))}
          </div>
        </div>
      );
    }
    
    
    슬라이드 색인이 바뀔 때마다 호출되는 함수resetTimeout to clearTimeout을 만들 것입니다.
    효과가 끝난 후에 청소를 하기 위해서 (구성 요소가 삭제되었을 때), 시간 초과를 제거하기 위해resetTimeout 함수를 호출합니다.
    const colors = ["#0088FE", "#00C49F", "#FFBB28"];
    const delay = 2500;
    
    function Slideshow() {
      const [index, setIndex] = React.useState(0);
      const timeoutRef = React.useRef(null);
    
      function resetTimeout() {
        if (timeoutRef.current) {
          clearTimeout(timeoutRef.current);
        }
      }
    
      React.useEffect(() => {
        resetTimeout();
        timeoutRef.current = setTimeout(
          () =>
            setIndex((prevIndex) =>
              prevIndex === colors.length - 1 ? 0 : prevIndex + 1
            ),
          delay
        );
    
        return () => {
          resetTimeout();
        };
      }, [index]);
    
      return (
        <div className="slideshow">
          <div
            className="slideshowSlider"
            style={{ transform: `translate3d(${-index * 100}%, 0, 0)` }}
          >
            {colors.map((backgroundColor, index) => (
              <div
                className="slide"
                key={index}
                style={{ backgroundColor }}
              ></div>
            ))}
          </div>
    
          <div className="slideshowDots">
            {colors.map((_, idx) => (
              <div
                key={idx}
                className={`slideshowDot${index === idx ? " active" : ""}`}
                onClick={() => {
                  setIndex(idx);
                }}
              ></div>
            ))}
          </div>
        </div>
      );
    }
    
    
    이제 원하는 대로 클릭하면 슬라이드가 계속 작동합니다.

    타이머 값이 지워졌습니다.

    더 많은 정보를 알고 반응하다


    실천에서 공부하는 것이 가장 좋다.다음은 Tinloof React 자습서입니다.
  • How to create React Notifications/Toasts
  • How to create an accessible React modal
  • Note: Tinloof is a Berlin-based product studio. Get in touch if you'd like us to help you build slick and fast web applications.

    좋은 웹페이지 즐겨찾기