본문 바로가기
부트캠프 개발일지 2023-2024/Bootcamp 생활기록

[7주차] 리액트: 버튼을 눌렀을 때 색 변하게 하기 (styled-components)

by whereanna00 2023. 11. 14.

 

현재 상황

 

  • <buttonI> 를 map 으로 돌려 총 4개의 버튼이 화면에 랜더링되는 상황
  • buttonText 정보와 각각의 아이디가 들어 있는 배열이 선언되어 있음

 

Task

  • 화면을 로딩했을 때, 첫번째 버튼이 눌려져 있어야 함
  • 4개 중 버튼은 하나만 누르는 것이 가능함
  • 버튼 활성화 시, 배경색이 검정 그리고 글자색이 흰색 비활성화 시, 배경색이 흰색 그리고 글자색이 검정색

 

해결방법

  • 화면을 로딩했을 때, 첫번째 버튼이 눌려져 있어야 함
  • 4개 중 버튼은 하나만 누르는 것이 가능함
  • 버튼 활성

 

 

 

 

전체코드 BEFORE

더보기

Button.jsx

import { styled } from 'styled-components';
import React from 'react';
import {useState} from 'react';
import { useEffect } from 'react';

const ButtonBox = styled.div`
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: center;
`;

const ButtonI = styled.button`
  width: 100px;
  height: 50px;
  font-size: 1rem;
  font-weight: 500;
  border: 1px solid black;
  transition: 0.2s ease;
  cursor: pointer;
  &:hover {
    background-color: black;
    color: white;
  }
`;
// background-color: ${selectedCharacterId === buttonText.id ? 'black' : 'white'};
// background-color: ${setPaulButtonActivated ? 'black' : 'white'};
// color: ${props => props.ButtonActivated ? 'white' : 'black'};

function Button({setPaulLetterShown,setElioLetterShown,  setGatsbyLetterShown, setLeeLetterShown})
{
  const [selectedCharacterId, SetSelectedCharacterId] = useState(1);

  const [buttonText, setButtonText] = useState(
    [
      {id:1, name: "Paul"},
      {id:2, name: "Elio"},
      {id:3, name: "Gatsby"},
      {id:4, name: "Lee"},
    ]
  );

  // 첫화면에 paul 버튼 활성화 세팅
  useEffect(()=> {
      // setPaulButtonActivated(true);
      // setElioButtonActivated(false);
      // setGatsbyButtonActivated(false);
      // setLeeButtonActivated(false);

      setPaulLetterShown(true);
      setElioLetterShown(false);
      setGatsbyLetterShown(false);
      setLeeLetterShown(false);
    }, []);

  const buttonByNameClickHandler = (item) => {
    SetSelectedCharacterId(item.id);
    switch (item.name) {
      case 'Paul':
        setPaulLetterShown(true);
        setElioLetterShown(false);
        setGatsbyLetterShown(false);
        setLeeLetterShown(false);
        break;
      case 'Elio':
        setElioLetterShown(true);
        setPaulLetterShown(false);
        setGatsbyLetterShown(false);
        setLeeLetterShown(false);
        break;
      case 'Gatsby':
        setGatsbyLetterShown(true);
        setElioLetterShown(false);
        setPaulLetterShown(false);
        setLeeLetterShown(false);
        break;
      case 'Lee':
        setLeeLetterShown(true);
        setGatsbyLetterShown(false);
        setElioLetterShown(false);
        setPaulLetterShown(false);
        break;
      default:
        break;
    }
  }


  return (
    <ButtonBox>
      {buttonText.map((item)=>{
        return(
          <ButtonI key={item.id} onClick={()=> buttonByNameClickHandler(item) } style={{
            backgroundColor: selectedCharacterId === item.id ? "black" : "white",
            color: selectedCharacterId === item.id ? "white" : "black",
          }}>{item.name}</ButtonI>
        );
      })}
    </ButtonBox>
  )
}

export default Button

 

 

리펙토링

  • <ButtonI> 태그 내에 인라인으로 들어가 있던 조건부 css 를 styled-components 방식에 따라 전역에서 선언되는 <ButtonI> 선언부쪽에 옮김
  • 옮기는 과정에서, props 방식을 통해 selectedCharacterId / buttonId 를 <ButtonI> 태그 컴포넌트에 전해줌
  • <ButtonI> 선언부 내에서는 동적인 조건부 스타일을 구현하기 위해 백틱안에서 함수요소를 다룰 때 쓰는 ${}로 감싸줌
  • () => () 형식으로 이루어지고, 삼항 연산자를 씀

 

 

전체코드 AFTER

더보기

Button jsx

import { styled } from 'styled-components';
import React from 'react';
import {useState} from 'react';
import { useEffect } from 'react';

const ButtonBox = styled.div`
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: center;
`;

const ButtonI = styled.button`
  width: 100px;
  height: 50px;
  font-size: 1rem;
  font-weight: 500;
  border: 1px solid black;
  transition: 0.2s ease;
  cursor: pointer;
  &:hover {
    background-color: black;
    color: white;
  }
  background-color: ${(props) => (props.selectedCharacterId === props.buttonId ? 'black' : 'white')};
  color: ${(props) => (props.selectedCharacterId === props.buttonId ? 'white' : 'black')};
`;

function Button({setPaulLetterShown,setElioLetterShown,  setGatsbyLetterShown, setLeeLetterShown})
{
  const [selectedCharacterId, SetSelectedCharacterId] = useState(1);

  const [buttonText, setButtonText] = useState(
    [
      {id:1, name: "Paul"},
      {id:2, name: "Elio"},
      {id:3, name: "Gatsby"},
      {id:4, name: "Lee"},
    ]
  );

  // 첫화면에 paul 버튼과 paul letters 활성화 세팅
  useEffect(()=> {
      setPaulLetterShown(true);
      setElioLetterShown(false);
      setGatsbyLetterShown(false);
      setLeeLetterShown(false);
    }, []);

  const buttonByNameClickHandler = (item) => {
    SetSelectedCharacterId(item.id);
    switch (item.name) {
      case 'Paul':
        setPaulLetterShown(true);
        setElioLetterShown(false);
        setGatsbyLetterShown(false);
        setLeeLetterShown(false);
        break;
      case 'Elio':
        setElioLetterShown(true);
        setPaulLetterShown(false);
        setGatsbyLetterShown(false);
        setLeeLetterShown(false);
        break;
      case 'Gatsby':
        setGatsbyLetterShown(true);
        setElioLetterShown(false);
        setPaulLetterShown(false);
        setLeeLetterShown(false);
        break;
      case 'Lee':
        setLeeLetterShown(true);
        setGatsbyLetterShown(false);
        setElioLetterShown(false);
        setPaulLetterShown(false);
        break;
      default:
        break;
    }
  }


  return (
    <ButtonBox>
      {buttonText.map((item)=>{
        return(
          <ButtonI key={item.id} onClick={()=> buttonByNameClickHandler(item) } selectedCharacterId={selectedCharacterId} buttonId={item.id}>{item.name}</ButtonI>
        );
      })}
    </ButtonBox>
  )
}

export default Button
728x90
반응형