ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스타일드 컴포넌트 조건부 렌더링 활용하기
    React.js & Next.js 2022. 8. 26. 22:51

    스타일드 컴포넌트 조건부 렌더링 활용하기

    프론트엔드 개발 환경에서 CSS-in-JS 를 사용하는 가장 큰 이점 중에 하나는 property를 css 에도 적용할 수 있다는 것일 것이다. 리액트에서 className 을 통해 조건부 렌더링 하는 것보다 state 를 전달하는 것이기 때문에 맥락을 파악하기 쉽고 이해하기도 쉽다. 이렇게 CSS-in-JS 중 스타일드 컴포넌트(styled-component) 를 잘 활용하는 방법을 소개해볼까 한다.

    CSS-in-JS의 장점은 재사용 가능한 컴포넌트로써 스타일링 코드의 양을 줄일 수 있고, 타입스크립트의 경우 props에 대한interface를 적극적으로 활용하여 더욱 가독성이 높은 코드를 만들 수 있다.

     

    코드 상에서는 다음과 같이 사용된다

    <button type='button' onClick={() => setIsHandsUpAlarmModal(true)}>
      {handsUpList.length ? (
        <AlarmActiveIcon fill='#fff' stroke='none' blink />
      ) : (
        <AlarmIcon fill='#fff' stroke='none' />
      )}
    </button>

    handsUpList 라는 배열이 있는데, 해당 배열이 0이상일 경우(데이터가 존재할 경우) AlarmActiveIcon 을 존재하지 않을 경우 AlarmIcon을 호출한다. 내부 fill 과 stroke를 모두 props로 전달한다.

     

    AlarmActiveIcon 컴포넌트

    import { IIconProps } from 'types';
    import * as S from './Icons_styles';
    
    const AlarmActiveIcon = (props: IIconProps) => {
      return (
        <S.IconWrap width={props.width} fill={props.fill} stroke={props.stroke} blink={props.blink}>
          <svg viewBox='0 0 25 25' xmlns='http://www.w3.org/2000/svg'>
            <path d='M7.58 4.08 6.15 2.65C3.75 4.48 2.17 7.3 2.03 10.5h2c.15-2.65 1.51-4.97 3.55-6.42zm12.39 6.42h2c-.15-3.2-1.73-6.02-4.12-7.85l-1.42 1.43c2.02 1.45 3.39 3.77 3.54 6.42zM18 11c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2v-5zm-6 11c.14 0 .27-.01.4-.04.65-.14 1.18-.58 1.44-1.18.1-.24.15-.5.15-.78h-4c.01 1.1.9 2 2.01 2z' />
          </svg>
        </S.IconWrap>
      );
    };
    
    export default AlarmActiveIcon;

    AlarmIcon 컴포넌트

    import { IIconProps } from 'types';
    import * as S from './Icons_styles';
    
    const AlarmIcon = (props: IIconProps) => {
      return (
        <S.IconWrap width={props.width} fill={props.fill} stroke={props.stroke}>
          <svg viewBox='0 0 25 25' xmlns='http://www.w3.org/2000/svg'>
            <path d='M12 22c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2zm6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z' />
          </svg>
        </S.IconWrap>
      );
    };
    
    export default AlarmIcon;

    이 코드는 IconWrap 이라는 공통 스타일드 컴포넌트를 사용하는 svg로 구현한 아이콘이다. 내부 스타일드 컴포넌트 코드는 다음과 같다.

    import styled from 'styled-components';
    
    interface IIconWrap {
      width?: number;
      fill?: string;
      stroke?: string;
    }
    
    export const IconWrap = styled.div<IIconWrap>`
      width: ${(props) => (props.width ? `${props.width}px` : '20px')};
      margin: 0 auto;
      path {
        fill: ${(props) => props.fill || '#000'};
        stroke: ${(props) => props.stroke || 'none'};
      }
    `

    'IIconWrap' 이라는 인터페이스는 모두 필수로 프로퍼티를 받는 것이 아닌 optional 처리가 되어있다. 기본적인 크기(width)와 색상(fill, stroke)는 유지한채 props로 전달받을 때마다 해당 값으로 변경해주는 것이다.

     

    특별한 점은 AlarmActiveIcon blink 라는 프로퍼티이다. 이 부분은 커스텀 아이콘이 액티브 상태일 때 깜빡이는 효과를 주기 위해 조건부로 넘겨받는 props이다. 기존에 스타일드 컴포넌트인 IconWrap 에서 단순하게 css 속성 하나에만 적용하는 것이 아닌, 여러 가지의 css 코드도 한 번에 적용할 수 있다.

     

    IIconWrap이라는 인터페이스에 blink 라는 boolean 타입을 가지는 props를 추가하였다. 이에 따라 필요한 에니메이션 효과를 구현하였다.

    import styled from 'styled-components';
    
    interface IIconWrap {
      width?: number;
      fill?: string;
      stroke?: string;
      blink?: boolean;
    }
    
    export const IconWrap = styled.div<IIconWrap>`
      width: ${(props) => (props.width ? `${props.width}px` : '20px')};
      margin: 0 auto;
      path {
        fill: ${(props) => props.fill || '#000'};
        stroke: ${(props) => props.stroke || 'none'};
      }
      ${({ blink }) =>
        blink &&
        `
            animation: blink 1s steps(5, start) infinite;
            -webkit-animation: blink 1s steps(5, start) infinite;
          }
          @keyframes blink {
            to {
              visibility: hidden;
            }
          }
          @-webkit-keyframes blink {
            to {
              visibility: hidden;
            }
    
      `}
    `;

     

    결과 보기

    단순히 한 가지의 css 를 위한 property를 전달하는 방법도 있지만, property 로 하여금 여러 개의 css를 선언할 수 있는 방법도 알아두면 유용하게 사용할 수 있을 것이다.

    댓글

Designed by Tistory.