React 슬라이드 페이지 만들기

여러 사이트에서 요금제 같은 것을 설명하기 위한 페이지를 보면,

해당 페이지 내, 상단에 메뉴 바가 존재하고 해당 메뉴 바를 클릭하면 그것에 알맞는 페이지로 변경이 되는 효과를 줍니다.

이러한 효과를 React 내에서 어떻게 구현하면 좋을지 한 번 도전해봤습니다. 

코드는 이렇게...

				
					const Plans = () => {
  return (
    <div className="plans-page">


      <div className="Free-Plan-Page">
        <img src={FreePlanPage} />

        <button className="Free-Go-Button">
          <img src={FreeGoButton} />
        </button>
      </div>



    </div>
  );
};

export default Plans;


//CSS 

.plans-page{
    margin-top: 5rem;
}

.Free-Plan-Page{
    position: relative;
}

.Free-Plan-Page img{
    width: 100%;
    height: auto;

}

.Free-Go-Button img{
    width: 100%;
    height: auto;
}

.Free-Go-Button{
    background-color: transparent;
    border: transparent;
    box-shadow: none;

    position: absolute;
    top: 70%; 
    left: 40%; 

}

.Free-Go-Button:hover{
    background-color: transparent;
    border: transparent;
    box-shadow: none;
}
				
			

왼쪽과 같은 코드를 통해 화면을 구성했을 때,

위와 같은 페이지가 나타나도록 설정했습니다.

단순히 Free Plan 에 관한 설명과 Free Plan 구독을 위한 버튼을 넣어둔 페이지입니다.

하지만, Plan 이 많아진다면? 

Simple, Standard, Premium 과 같은 Plan 이 존재한다고 가정할까요?

이런 Plan 에 대해서 설명하고, 구독하기 위한 버튼이 있는 페이지를 세로로 줄줄이 나열하는 건 별로 좋지 않을 것 같죠?

가시성이나 사용자의 편의를 위해서 저는 상단에 가로로 Bar 을 하나 두고 

해당 Bar 내부에 있는 Plan 이름을 클릭하면 해당하는 페이지가 화면에 나타나도록 할 겁니다!

그럼 이를 위해서 어떤 식으로 코드를 구성하면 좋을지 보겠습니다. 

				
					import React from "react";
import { useNavigate } from "react-router-dom";
import "./plans.css";

const Plans = () => {
  const navigate = useNavigate();

  const handleNavigate = (plan) => {
    navigate(`/plans/${plan}`);
  };

  return (
    <div className="plans-page">
      <div className="plans-nav">
        <button onClick={() => handleNavigate("free")}>Free</button>
        <button onClick={() => handleNavigate("simple")}>Simple</button>
        <button onClick={() => handleNavigate("standard")}>Standard</button>
        <button onClick={() => handleNavigate("premium")}>Premium</button>
      </div>

      {/* 기존 Free-Plan-Page 컴포넌트 */}
      {/* 다른 플랜 페이지도 여기에 추가 */}
    </div>
  );
};

export default Plans;

				
			

먼저, 왼쪽과 같은 형태로 코드를 개조할 겁니다.

plans/free 로 이동하면 free 관련 페이지가..

plans/simple 로 이동하면 simple 관련 페이지가 나타날 수 있도록 하는 겁니다.

아래처럼 하나의 파일 내에서 여러 컴포넌트를 지정해두고, 

그걸 가져와서 사용하는 방식으로 짤 겁니다. 

				
					const FreePlan = () => {

}

const SimplePlan = () => {

}

// ... 이런 식으로 각 Plan 의 컴포넌트를 쭉 생성해둠.

const Plans = () => {

    return(

     <FreePlan />
     <SimplePlan />  // ... 이쪽에서 가져와서 사용하기. 
    )
}
				
			

약간 응용을 하자...

위 코드는 URL 이 변경되는 형태입니다.

다만, 저는 쓸데없이 URL 이 변경되면서 페이지가 넘어가는 것보다는, 하나의 페이지 안에서 유동적으로 변경이 되는 것을 원합니다.

그러니까, 각 컴포넌트에 ShowField 라는 인자를 집어 넣어서, 이것이 True 을 때는 보이고, False 일 때는 보이지 않는 형식을 사용해보겠습니다. 

				
					const FreePlan = ({ ShowField }) => {
  if (ShowField) {
    return (
      <div className="Free-Plan-Page">
        <img src={FreePlanPage} alt="Free Plan" />
        <button className="Free-Go-Button">
          <img src={FreeGoButton} alt="Go Button" />
        </button>
      </div>
    );
  } else {
    return null;
  }
};

const Plans = () => {
  const [ShowFree, setShowFree] = useState(true);
  const [ShowSimple, setShowSimple] = useState(false);
  const [ShowStandard, setShowStandard] = useState(false);
  const [ShowPremium, setShowPremium] = useState(false);

  const handleShowFree = () => {
    setShowFree(true);
    setShowSimple(false);
    setShowStandard(false);
    setShowPremium(false);
  };

  const handleShowSimple = () => {
    setShowFree(false);
    setShowSimple(true);
    setShowStandard(false);
    setShowPremium(false);
  };

  const handleShowStandard = () => {
    setShowFree(false);
    setShowSimple(false);
    setShowStandard(true);
    setShowPremium(false);
  };
  const handleShowPremium = () => {
    setShowFree(false);
    setShowSimple(false);
    setShowStandard(false);
    setShowPremium(true);
  };

  return (
    <div className="plans-page">
      <div className="plans-nav">
        <button onClick={() => handleShowFree()}>Free</button>
        <button onClick={() => handleShowSimple()}>Simple</button>
        <button onClick={() => handleShowStandard()}>Standard</button>
        <button onClick={() => handleShowPremium()}>Premium</button>
      </div>

      <FreePlan ShowField={ShowFree} />
    </div>
  );
};

export default Plans;
				
			

위 코드는 plans-nav  내에서 버튼을 누르면 해당 버튼이 각 plan 에 대한 Show 변수를 True 또는 False 로 변경합니다.

handleShowFree 를 누르면 Free 에 관한 Show 변수만 True 가 되고 나머지는 False 가 되는 방식이고, 

다른 handleShow 함수도 마찬가지 식으로 갑니다.

여기서 FreePlan 이라는 컴포넌트에서 ShowField 가 False 라면 Null 을 반환하고, 아니라면 기존 페이지를 반환하게 됩니다.

이제 FreePlan 과 마찬가지로 다른 Plan 의 컴포넌트도 똑같이 만들겠습니다.

그럼 이제 전체 코드를 먼저 놓고, 해당 코드를 통해서 나타나는 페이지를 보겠습니다.

먼저 전체 코드입니다. 

				
					import React, { useState } from "react";
import "./plans.css";

//SVG Import
import FreePlanPage from "../img/plan/test/Test-Free.svg";
import FreeGoButton from "../img/plan/test/Test-Button.svg";

import SimplePlanPage from "../img/plan/test/Test-Simple.svg";
import SimpleGoButton from "../img/plan/test/Test-Button.svg";

import StandardPlanPage from "../img/plan/test/Test-Standard.svg";
import StandardGoButton from "../img/plan/test/Test-Button.svg";

import PremiumPlanPage from "../img/plan/test/Test-Premium.svg";
import PremiumGoButton from "../img/plan/test/Test-Button.svg";

const FreePlan = ({ ShowField }) => {
  if (ShowField) {
    return (
      <div className="Free-Plan-Page">
        <img src={FreePlanPage} alt="Free Plan" />
        <button className="Free-Go-Button">
          <img src={FreeGoButton} alt="Go Button" />
        </button>
      </div>
    );
  } else {
    return null;
  }
};

const SimplePlan = ({ ShowField }) => {
  if (ShowField) {
    return (
      <div className="Simple-Plan-Page">
        <img src={SimplePlanPage} alt="Simple Plan" />
        <button className="Free-Go-Button">
          <img src={SimpleGoButton} alt="Go Button" />
        </button>
      </div>
    );
  } else {
    return null;
  }
};

const StandardPlan = ({ ShowField }) => {
  if (ShowField) {
    return (
      <div className="Standard-Plan-Page">
        <img src={StandardPlanPage} alt="Standard Plan" />
        <button className="Standard-Go-Button">
          <img src={StandardGoButton} alt="Go Button" />
        </button>
      </div>
    );
  } else {
    return null;
  }
};

const PremiumPlan = ({ ShowField }) => {
  if (ShowField) {
    return (
      <div className="Premium-Plan-Page">
        <img src={PremiumPlanPage} alt="Premium Plan" />
        <button className="Premium-Go-Button">
          <img src={PremiumGoButton} alt="Go Button" />
        </button>
      </div>
    );
  } else {
    return null;
  }
};

const Plans = () => {
  const [ShowFree, setShowFree] = useState(true);
  const [ShowSimple, setShowSimple] = useState(false);
  const [ShowStandard, setShowStandard] = useState(false);
  const [ShowPremium, setShowPremium] = useState(false);

  const handleShowFree = () => {
    setShowFree(true);
    setShowSimple(false);
    setShowStandard(false);
    setShowPremium(false);
  };

  const handleShowSimple = () => {
    setShowFree(false);
    setShowSimple(true);
    setShowStandard(false);
    setShowPremium(false);
  };

  const handleShowStandard = () => {
    setShowFree(false);
    setShowSimple(false);
    setShowStandard(true);
    setShowPremium(false);
  };
  const handleShowPremium = () => {
    setShowFree(false);
    setShowSimple(false);
    setShowStandard(false);
    setShowPremium(true);
  };

  return (
    <div className="plans-page">
      <div className="plans-nav">
        <button onClick={() => handleShowFree()}>Free</button>
        <button onClick={() => handleShowSimple()}>Simple</button>
        <button onClick={() => handleShowStandard()}>Standard</button>
        <button onClick={() => handleShowPremium()}>Premium</button>
      </div>

      <FreePlan ShowField={ShowFree} />
      <SimplePlan ShowField={ShowSimple} />
      <StandardPlan ShowField={ShowStandard} />
      <PremiumPlan ShowField={ShowPremium} />
    </div>
  );
};

export default Plans;
				
			

그럼 이제 위 코드를 통해서 나타나는 페이지입니다. 

위쪽에 버튼만 나타나서 별로 이쁘지는 않습니다.

아래와 같이 CSS 를 추가해서 위쪽 Bar를 꾸며주겠습니다. 

				
					/*nav-bar design */
.plans-nav {
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: bisque;
  }
  
  .plans-nav button {
    margin: 0 10px;
    padding: 10px 20px;
    background-color: transparent;
    border: 1px solid #ddd;
    cursor: pointer;
  }
  
  .plans-nav button:hover {
    background-color: #e0e0e0;
  }
				
			

마치며..

하나의 페이지 안에서 특정한 버튼을 통해서 어떠한 컴포넌트를 보이게 하고, 숨기게 하는 로직은 아주 유용하게 써먹을 수 있을 것 같습니다.

이전에 이런 동작을 팝업창에 써먹였죠?  React로 팝업창 구현하기

굳이 컴포넌트 별로 파일을 여러 개 만들지 않고, 이런 식으로 관리하는 법이 개인적으로 훨씬 수월한 것 같습니다^^