[React] styled-components {css} #조건에 따른 CSS 처리

styled-components로 조건에 맞게 스타일링을 하면 개인적으로 가독성이 많이 떨어진다고 생각한다. 항상 불편함을 느꼈지만 모른채하고 그냥 쓰고 있었는데 어쩌다보니 알게된 {css} 라이브러리를 써보고 마음이 편안해져버렸다.. 

 

💡 일단 코드부터 바로
import styled, { css } from 'styled-components';

const COLORS = {
  warn: css`
    background-color: red;
    color: white;
  `,
  default: css`
    background-color: black;
    color: white;
  `,
};

const StBtn = styled.button`
  ${(props) => props.colorStyle}
  border: none;
  padding: 3px 5px 3px 5px;
  border-radius: 4px;
`;

const Button = ({ text, type = 'default', id, action }) => {
  const colorStyle = COLORS[type];

  return (
    <StBtn colorStyle={colorStyle}>{text}</StBtn>
  );
};

💡 기본 styled-components

styed-components로 조건에 맞게 스타일링을 적용하는 여러가지 방법이 있다. `styled` 내부에서 삼항연산자를 사용하거나, 함수를 만들던지, 객체를 만들어서 매핑을 시켜준다던지.. 편한 방법으로 쓰면 된다. 

하지만 개인적으로 가독성이 좋지 않다고 느껴져 삼항연산자를 쓰는 방법은 선호하지 않았다. 그래서 객체나 함수를 사용하자니 얘네도 썩 마음에 드는 형태로 생기지 않았다. 

대충 예시 코드로 확인해보자.

 

삼항연산자

<StBtn type={'warn'}>
  {text}
</StBtn>

const StBtn = styled.button`
  background-color: ${props => props.type === 'warn' ? 'red' : 'white'};
  color: ${props => props.type === 'warn' ? 'white' : 'black'};
  border: none;
  padding: 3px 5px 3px 5px;
  border-radius: 4px;
  `;

조건으로 처리하는 속성이 2개만 있어도 복잡하고 보기 싫게 생겼다. 그래서 함수로 분리해보았다.

 

함수에서 조건 처리 (1) - 모든 속성마다 함수 정의

/* 생략 */
const getBgColor = (type) =>{
  switch(type){
    case 'warn':
      return 'red';
    default:
      return 'white'
  }
}

const getColor = (type) => {/* 생략 */}

const StBtn = styled.button`
  background-color: ${props => getBgColor(props.type)};
  color: ${props => getColor(props.type)};
  border: none;
  padding: 3px 5px 3px 5px;
  border-radius: 4px;
`;

뭐 대충 이렇게 사용하던가 해야한다. 개인적으로 삼항 연산자보다는 쪼~끔 더 괜찮게 생긴 것 같다. 하지만 같은 `타입`인데도 필요한 속성마다 함수를 전부 정의하고, 호출하는건 꽤나 불필요한 작업이라고 생각한다. 

 

함수에서 조건 처리 (2) - 하나의 함수에서 전부 반환

const getButtonStyles = (type) => {
  switch (type) {
    case 'back':
      return {
        backgroundColor: 'black',
        color: 'white',
      };
    default:
      return {
        backgroundColor: 'red',
        color: 'white',
      };
  }
};

const StBtn = styled.button`
  ${({ type }) => {
    const styles = getButtonStyles(type);
    return `
      background-color:${styles.backgroundColor};
      color:${styles.color};
  `;
  }}
  border: none;
  padding: 3px 5px 3px 5px;
  border-radius: 4px;
`;

어처피 공통 변수 `type`으로 분기를 처리하니 하나의 함수에서 `backgroundColor`, `color` 를 전부 반환하도록 변경했다.  개인차가 있겠지만 이전 코드들에 비해서는 깔끔해졌다고 생각이 든다. 특히 `type` 별 속성에 대한 스타일을 하나의 블록안에서 처리가 가능해졌다는게 가장 큰 장점이 아닐까 싶다. 

그래도 초보 개발자의 시선에서 코드가 팍 하고 바로 읽히지는 않는 것 같다. 따라서 styled-components의 `css` 라이브러리를 함께 import해서 변경해보았다. 

 

 

💡 styled-components의 {css} 라이브러리 사용

예시코드

import styled, { css } from 'styled-components';

const COLORS = {
  warn: css`
    background-color: red;
    color: white;
  `,
  default: css`
    background-color: black;
    color: white;
  `,
};

const StBtn = styled.button`
  ${(props) => props.colorStyle}
  border: none;
  padding: 3px 5px 3px 5px;
  border-radius: 4px;
`;

const Button = ({ text, type = 'default', id, action }) => {
  const colorStyle = COLORS[type];

  return (
    <StBtn colorStyle={colorStyle}>{text}</StBtn>
  );
};

코드가 정말 많이 깔끔해졌다.  사용법도 간단하다. 

  • css를 import한다.
  • 객체 형태로 type에 대한 map(객체)을 만들어준다. 
  • styled에서 반환하면 별도의 속성지정하지 않아도 알아서 바로 적용된다.

댓글

Designed by JB FACTORY