[React] Click 이벤트 한 버튼만, 활성화 해보자! (feat. React, tailwind-styled-components)

비트·2023년 11월 20일

React

목록 보기
5/12
post-thumbnail

🔥Click 이벤트! 한 버튼만! 활성화 해보자! (feat. React, tailwind-styled-components)

포트폴리오를 작업하는 과정에서..

" 헤더 버튼에서 클릭 이벤트가 발생하면 메인 부분이 바뀌지만, 좀 더 직관적으로 어느 부분인지 알려 줄 수는 없을까? "

라는 생각에 헤더를 Click을 했을때 해당 버튼이 눌려 있게 하는 기능을 추가하기러 했다.


🤔 active? focus?

처음으로 부딪힌 부분은 클릭을 하고 있을 때 주어야 하는 CSS 효과였다.

HTML, CSS 과정은 수도 없이 공부하고 함께 했지만.. 잘 안쓰는 기능들은 늘 새롭게 느껴지는...😂

  • hover : 마우스를 커서가 올라가 있는 상태.
  • focus : 초점 요소에 클릭을 해서 초점이 맞춰져 있는 상태.
  • active : 활성화 요소가 클릭되어 활성화 되어 있는 상태.

✔️ 각각의 버튼 클릭시 active 여부를 줘야 한다!

  • 그냥 focus를 주면 바로 클릭이 되었을때 초점이 맞춰지기 때문에 '어라...?' 했지만, 여기에는 큰 에러가 있었다..ㅎㅎ😂
  • focus를 줄 경우 다른 버튼을 클릭시 해당 버튼에 focus가 풀리면서 다른 버튼에 focus는 먹히지 않는 이슈가 발생!😶‍🌫️😶‍🌫️
  • 알아본 결과 useState를 사용해서 상태를 boolean으로 설정해 active가 눌려 있도록 값을 전달해줘야 한다!
    • 이렇게 하면 true일때는 active가 되어 초점이 계속 맞춰져 있어 클릭이 되어 있는 상태가 되고 false가 되면 클릭이 풀리게 되어 다른 버튼 클릭시 바로 적용이 된다.

🚑 그런데 문제 발생!

tailwind를 사용하다 보니 className에 style을 적용하고 있어서 알아본 방법으로는 className + active 설정을 할 수가 없는 상황...😭

  • useState를 사용해서 boolean까진 초기값 설정을 했는데... 하나를 클릭하면 전체가 다 active가 되어요....🫠🫠
    tailwind가 정말 편리한데 요렇게 몇몇 불편할때가 발생한다..
  • 자.. 우선 indexkey를 써야할거 같은데...
    • 결론부터 말하자면, 다행히도 사수님에 도움으로 무사히 해결되었다!🤕


import tw from "tailwind-styled-components";
import React, { useState } from "react";

function App() {
  const Button = tw.button`
  bg-red-100
  mx-10
  py-4
  px-4
  md:px-8
  cursor-pointer
  border
  border-red-100
  shadow-lg
  rounded-full
  transition-all
  duration-300
  hover:bg-red-300
  hover:border-red-300
  hover:shadow-inner
  hover:underline
  flex 
  items-center 
`;
  const TitleText = tw.h1`
  text-[3rem] 
  md:text-[4rem] 
  lg:text-[5rem] 
  text-center 
  text-white 
  font-extrabold
  `;

  const sections = [
    {
      name: "Home",
      component: <Home Button={Button} TitleText={TitleText} />,
    },
    {
      name: "Portfolio",
      component: <Portfolio Button={Button} TitleText={TitleText} />,
    },
    {
      name: "Stack",
      component: <Stack TitleText={TitleText} />,
    },
  ];

  const [section, setSection] = useState(sections[0].component);

  return (
    <div
      className="w-full h-screen"
      style={{
        backgroundImage:
          "linear-gradient(180deg, rgb(255, 187, 187) -34.2%, rgba(255, 102, 102, 0.40) 42.5%, rgba(255, 0, 0, 0.00) 223.53%)",
      }}
    >
      <Header setSection={setSection} sections={sections} Button={Button} />
      <Main section={section} />
    </div>
  );
}

export default App;

헤더에 상위인 App.js 코드.

  • tailwind만으로 사용하면 className이 지저분해지기 때문에 tailwind + styled-components 가 결합된 tailwind-styled-components를 사용해서 CSS를 사용했다!
    • 정보가 많이 나와있지 않아서 골치가 아픈 부분.. (다음엔 CSS로 작업할거 같다..)
  • 선언한 Button은 상속으로 내려주서 커스텀해주어 사용했다.

import React from "react";
import { useState } from "react";
import tw from "tailwind-styled-components";

const Header = ({ setSection, sections, Button }) => {
  const HeaderButton = tw(Button)`
    mt-4 
    md:mt-8 
    lg:mt-6 
    mx-2.5 
    md:mx-8 
    lg:mx-12 
    px-8 
    hover:text-white
  `;

  const action = " text-white bg-red-300 border-red-300 shadow-inner underline";
  const [isActive, setIsActive] = useState({ 0: true });

  return (
    <header className="w-full pt-5">
      <nav className="w-full text-2xl font-bold flex justify-center text-gray-800 my-2">
        {sections.map((headerButton, idx) => (
          <HeaderButton
            className={isActive[idx] && `${action}`}
            key={headerButton.name}
            onClick={() => {
              setSection(headerButton.component);
              setIsActive((pre) => ({ [idx]: !pre[idx] }));
            }}
          >
            {headerButton.name}
          </HeaderButton>
        ))}
      </nav>
    </header>
  );
};

export default Header;
  • HeaderButton

    • HeaderButton으로 커스텀 해주고 hover기능을 넣어 글자색도 바뀌도록 해주었다.
  • action

    • 이후 action을 선언해서 CSS 기능을 넣어주고 클릭한 상태에 값과 일치할 경우 className에 넣어주어 일치할 경우 CSS가 작동하도록 코드를 작성하였다.
  • const [isActive, setIsActive] = useState({ 0: true });

    • 초기값은 처음 페이지가 열리는 Home 부분이어야 하므로 0번째 index로 지정해주었다.
    • setIsActive((pre) => ({ [idx]: !pre[idx] }));
      • 각 인덱스에 값을 클릭했을 때 boolean 값이 반대가 되도록 함수 설정.

이렇게 하면 tailwind 를 사용하면서 className 지정 없이 index를 통해 상태를 설정할 수 있게 된다!

혼자 했다면... 정말 울면서 까마득했을 이슈.. 두 번은 일어나지 않았으면 하는 마음과 같은 일을 겪을 분들을 위해 기록합니다..😂

profile
Drop the Bit!

0개의 댓글