[React] 라이브러리 없이 슬라이드 구현하기(feat. 버튼 생성, 삭제)

Joah·2022년 6월 24일
4

React

목록 보기
20/31
post-thumbnail

✅React로 라이브러리 없이 슬라이드 구현 (px로 처리하기)

구조 파악하기

  • 미국고전영화 텍스트 밑에 카페 사진과 바다 사진이 있다. 각각의 요소가 원래는 영화 포스터가 자리해야 한다.(저작권 문제로 일단은 보류)

  • 해당 콘텐츠는 첫 화면에서 5개가 보여진다. 콘텐츠 5개의 길이는 1375px이다

  • 오른쪽 버튼을 누르면 요소들이 x축을 기준으로 -1375만큼 왼쪽으로 휙 밀려나게 된다.

  • 다음 콘텐츠들도 똑같이 width가 1375px이다.



🔑버튼이 클릭되면 1375px 씩 이동하라

먼저 1375px씩 이동하려면 아래의 스타일링을 부여해야 하는데,,,
중요한 건 1375px씩이다. SCSS에 작성하면 0에서 1375px 이동하고 끝이다.

  • 한 번 클릭 ▶️(-)1375px
  • 두 번 클릭 ▶️(-)1375px + (-)1375px
  • 세 번 클릭 ▶️(-)1375px + (-)1375px + (-)1375px
    문제를 해결하기 위해.....

🙌SCSS로 해결할 수 없으니 이동되는 px을 state로 관리해야 한다.🙌

//MainBox.js

const [slidePx, setSlidePx] = useState(0);

return(
<ul className="filmList">
  {movies.map(movie => (
   <Film slide={slidePx} key={movie.id} movie={movie} />
  ))}
</ul>
);

<MainBox/>의 자식 컴포넌트인 <Film/>slidePx을 넘겨준다.

//Film.js

const Film = ({ movie, slide }) => {
  const { id, name, release_date, image_url } = movie;
  return (
    <li
      className="film"
      id={id}
      style={{
        transform: `translateX(${slide}px)`,
        transition: "0.5s ease",
      }}
    >

propsslidePx을 넘겨 받아 <li> 태그 안에 인라인 스타일링으로

transform : translateX(${slide}px)을 부여한다.
📌인라인 스타일링을 지양하지만 필요할 때는 사용한다. 사실 절대 사용하면 안되는 것으로 알아서 어떻게든 다른 방법을 선택하려 했지만 필요에 의해서는 당연히 사용해도 된다.

//MainBox.js

<div className="prevBtn">
    <i className="fa-solid fa-chevron-left" />
</div>
<div className="nextBtn">
    <i className="fa-solid fa-chevron-right" />
</div>
  • 우선 버튼을 생성한다. <button>태그를 사용해도 되지만 SCSS를 편하게 작성하기 위해서 <div>안에 아이콘을 부여한다.
  • prevBtn은 이전으로 가는 버튼
  • nextBtn은 다음으로 가는 버튼


🙌버튼이 클릭되면... 그럼 onClick이지!🙌

//MainBox.js

<div className="prevBtn" onClick={toPrev}>
    <i className="fa-solid fa-chevron-left" />
</div>
<div className="nextBtn" onClick={toNext}>
    <i className="fa-solid fa-chevron-right" />
</div>

💡prevBtn이 클릭되면 현재 위치에서(slidePx) +1375px씩 움직인다.

//MainBox.js

const MainBox = ({ movies }) => {
  const [slidePx, setSlidePx] = useState(0);

  const toPrev = () => {
    if (slidePx < 0) setSlidePx(slidePx + 1375);
  };
}

📌 slidePx이 한 번이라도 이동된 상태일 때 즉, slidePx이 0보다 작을 때

  • prevBtn이 클릭되면 slidePx + 1375px

  • slidePx이 0일 때는 최초 화면이다. 아무 버튼을 누르지 않았을 때

  • 보통 이전 버튼은 최초화면 일때는 비활성화 되어있다. 지금 보여지는 화면보다 이전의 콘텐츠가 없기 때문이다.

  • 따라서, 이전 버튼은 콘텐츠들이 한 번 넘겨졌을 때 필요하다. 즉, x축으로 최대(음수니깐) - 1375px 움직여야 이전 버튼을 누를 수 있다.

  • 그럼 prevBtnslidePx이 0보다 작을 때 눌려야 한다. 그렇지 않고 눌리게 되면 아무런 콘텐츠를 보여주지 않는 화면으로 계속 이동한다.



🙌nextBtn이 클릭되면 현재 위치에서(slidePx) -1375px씩 움직인다.🙌

//MainBox.js

const MainBox = ({ movies }) => {
  const [slidePx, setSlidePx] = useState(0);

  const toNext = () => {
    if (slidePx > -2750) setSlidePx(slidePx - 1375);
  };
}
  • 반대로 다음에 보여질 콘텐츠가 없다면, 내가 준비한 콘텐츠가 10개라면, nextBtn이 한 번 클릭되고 더 이상 클릭되면 안된다. 15개라면, 2번....

  • 따라서, 현재 slidePx 값이 -2750px 보다 클때만(음수니깐 -1375px이 -2750px보다 큰 개념) -1375px 만큼 움직이게 조건을 작성한다.


👌버튼을 클릭하면 원하는 px 만큼 움직여라 로직 완성!!

//MainBox.js

const [slidePx, setSlidePx] = useState(0);

const toPrev = () => {
  if (slidePx < 0) setSlidePx(slidePx + 1375);
};

const toNext = () => {
  if (slidePx > -2750) setSlidePx(slidePx - 1375);
};


🔑보여질 콘텐츠가 없을 때 해당 방향의 버튼을 비활성화!

//MainBox.js

<div className="prevBtn" onClick={toPrev} style={{ display: slidePx === 0 ? "none" : "" }}>
    <i className="fa-solid fa-chevron-left" />
</div>
<div className="nextBtn" onClick={toNext} style={{ display: slidePx === -2750 ? "none" : "" }}>
    <i className="fa-solid fa-chevron-right" />
</div>

전설의 인.자.부 무시하기...
라인 스타일 탁(동기가 당부한 말)

각 버튼에 style 속성을 부여한다.
삼항 연산자를 사용해서

▶️ prevBtn

  • slidePx이 0이라면 즉, 초기화면 이라면 true일 때 display: none
    false라면 display: ""
    "block"을 작성하면 css가 삐뚤어짐..그냥 빈 문자열 줘도 됩니다. 어차피 기본 값이 "block"이기 때문이죠

▶️ nextBtn

  • slidePX이 -2750이라면 즉, 나의 프로젝트 기준으로 모든 콘텐츠를 보여줬을 때의 px이 2750px이기 때문! 여튼 true일 때 display: "none" false라면 display : ""

어땠나요..?

해당 슬라이드를 React가 아닌 Javascript로 구현한 적이 있다.
처음에는 이걸 어떻게 React로 옮기지...? 심각한데?

그렇게 이틀 동안 구상했다. 썼다 지웠다. 버튼이 활성화 되어야 할 곳에서 비활성화 되고 픽셀이 자꾸 안 맞고...

아주 간단한 로직임에도 한 번 소용돌이 빠지니 작은 오타도 못찾아내는 바보가 되어버린다.
이럴때는 빠져나와 다른 코드를 작성하고 구현해 보다가 다시 돌아오자. 멘토님이 살려주셨다.

막상 작성하니 코딩을 아예 모르는 사람에게 5분안에 설명해도 이해할 정도로 간단한 코드였다.

위의 코드를 리팩토링 해야 하지만 잊어버리기 전에 후딱 작성했다.

완벽히 이해해서 기분이 좋다. 슬라이드가 없는 웹페이지는 거의 없기 때문에 정말 많이 쓰일 것 같다.

지금 다시 보니 Javascript 보다 훨씬 간단하고 쉽게 React로 구현할 수 있었다!!!!


⛳ 다시 작성합니다! 위의 코드를 추후에 수정했습니다! (feat.조건부 렌더링)

import React, { useState } from "react";
import Film from "./../Film/Film";
import "./MainBox.scss";

const MainBox = ({ movies, theme }) => {
  const [slidePx, setSlidePx] = useState(0);

  const toPrev = () => {
    slidePx < 0 && setSlidePx(slidePx + 1375);
  };

  const toNext = () => {
    slidePx > -4125 && setSlidePx(slidePx - 1375);
  };
  if (!movies) return;
  return (
    <div className="mainBox">
      <p className="filmTheme">{theme.title}</p>
      <ul className="filmList">
        {movies.map(movie => (
          <Film slide={slidePx} key={movie.id} movie={movie} />
        ))}
      </ul>
      <div
        className="prevBtn"
        onClick={toPrev}
        style={{ display: slidePx === 0 ? "none" : "" }}
      >
        <i className="fa-solid fa-chevron-left" />
      </div>
      <div
        className="nextBtn"
        onClick={toNext}
        style={{ display: slidePx === -4125 ? "none" : "" }}
      >
        <i className="fa-solid fa-chevron-right" />
      </div>
    </div>
  );
};

export default MainBox;
profile
Front-end Developer

1개의 댓글

comment-user-thumbnail
2022년 6월 26일

잘보고가요!!!

답글 달기