-
스타일드 컴포넌트 조건부 렌더링 활용하기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를 선언할 수 있는 방법도 알아두면 유용하게 사용할 수 있을 것이다.
'React.js & Next.js' 카테고리의 다른 글
Next.js - SSR, getServerSideProps 적용하기 (0) 2022.09.18 Next.js - 초기화 이후 기본 구조 설정하기 (0) 2022.09.18 리액트에서 다수의 체크 박스 다루기 (0) 2022.09.13 자바스크립트 프로젝트에 타입스크립트 도입하기 (0) 2022.08.24 리액트 18 > 17 마이그레이션하기 (0) 2022.08.23