As i wish

Styled-component 에 props 로 style 적용 본문

React JS

Styled-component 에 props 로 style 적용

어면태 2020. 1. 1. 22:41

styled-component를 쓰면서 가장 큰 장점은 스타일링이 템플릿 리터럴(Template Literal)을 사용하기 때문에 $ <- 이부분으로 마음대로 스타일을 보다 쉽게 적용 할 수 있다는 점이 엄청난 장점입니다.

const Container = styled.div`
    width: 100%;
    position: fixed;
    background-color: white;
    bottom: 0;
    border-top: 1px solid ${pointColor};
    display: flex;
    text-align: center;
    z-index: 5;
`;

const Content = styled.div`
    padding: 10px;
    text-align: initial;
    & div {
        font-size: 10px;
    }

    ${isMobile} {
        display: none;
    }
`;

실제 styled-component 를 사용할 때에 이런식으로 사용하고 모듈은

export const pointColor = 'red';
export const subPointColor = '#384aa5';
export const lightGrayColor = '#8080802b';

export const navBarHeight = '75px';
export const footerHeight = '60px';

export const sideBarWidth = '280px';

export const mobileNavBar = '50px';

export const isMobile = '@media (max-width: 768px)';

이런식으로 따로 만들어서 관리를 하고 있습니다.

이렇게 되면 장점이 sass나 css 를 사용 할 때에 각각의 color는 sass, css 안에서만 관리가 되는데, 이를 JS 레벨 까지 끌어올릴 수 있게 되죠. 또한 스타일을 동적으로 만들 수 있어서 여러 클래스를 만들지 않아도 style 이 js 파일로 되어있어서 쉽게 가져다가 쓸 수 있게 됩니다.

사실 더 잘게 나누게 되면 다음과 같이 나눌 수 있게 되죠. 이렇게 되면 편리한 점이 js 내에서도 mobileMaxWidth 를 사용할 수 있게 된다는 점이죠. 실제 코딩을 하게 되면 sass, css내에서는 미디어쿼리를 통하여 mobile/pc일 경우 에 따라 다양한 반응형 웹을 만들게 되는데, mobile/pc를 나누는 정보가 sass, css내에 있다보니 js 내에서 사용할 때에는 따로 파일을 관리해줘야하는 불편함이 있게 됩니다. 그러나 styled-component 를 사용하게 되면 모든게 다 js파일에 있다보니 필요한 곳에 적재적소로 사용할 수 있어 아주 편하게 됩니다.

CSS-in-JS!!!!

const mobileMaxWidth = 768;
const isMobile = '@media (max-width: ${mobileMaxWidth}px)';

일례로 

import React from 'react';

import styled from 'styled-components';

import PropTypes from 'prop-types';

import { isMobile } from '../../styles/style';

const Container = styled.div`
    margin-bottom: 10px;
    display: flex;
    width: 100%;
    height: ${(props) => (props.isMenu ? '30px' : '')};
    background-color: ${(props) => (props.isMenu ? '#8080804d' : 'transparent')};
`;

const Number = styled.div`
    min-width: 20%;
    margin: auto 0;
    padding-left: 1%;
`;

const Content = styled.div`
    min-width: 40%;
    margin: auto 0;
    padding-left: 1%;
`;

const InputContainer = styled.div`
    min-width: 38%;
    display: flex;
`;

const InputContent = styled.div`
    width: 100%;
    margin-top: ${(props) => (props.isMenu ? 'auto' : '0')};
    margin-bottom: ${(props) => (props.isMenu ? 'auto' : '0')};
    margin-left: 0;
    display: flex;
    & input {
        font-size: 16px;
        text-align: center;
        width: 40px;
        height: 20px;
        margin: auto 0;
        ${isMobile} {
            width: 20px;
        }
    }
`;

const ButtonContainer = styled.div`
    cursor: pointer;
    border: 1px solid black;
    padding: 5px;
    box-shadow: 1px 1px black;
    display: flex;
    margin-top: auto;
    margin-bottom: auto;
    margin-left: auto;
    max-height: 20px;
    &: active {
        box-shadow: none;
        margin-left: 1px;
        margin-right: -1px;
    }
    & div {
        margin: auto;
    }
`;

const ShopItemDetailInfo = ({
    content, number, onChangeInputCount, onClickAddBascket, isMenu,
}) => (
    <Container isMenu={isMenu}>
        <Number>
            {number}
        </Number>
        <Content>
            {content}
        </Content>
        <InputContainer>
            <InputContent isMenu={isMenu}>
                {
                    isMenu
                        ? (
                            <div>
                                {'수량'}
                            </div>
                        )
                        : (
                            <>
                                <input onChange={onChangeInputCount} placeholder={0} type="number" min="0" />
                                <ButtonContainer onClick={onClickAddBascket}>
                                    <div>
                                        {'장바구니'}
                                    </div>
                                </ButtonContainer>
                            </>
                        )
                }
            </InputContent>
        </InputContainer>
    </Container>
);


ShopItemDetailInfo.propTypes = {
    number: PropTypes.string,
    content: PropTypes.string,
    isMenu: PropTypes.bool,
    onChangeInputCount: PropTypes.func,
    onClickAddBascket: PropTypes.func,
};

ShopItemDetailInfo.defaultProps = {
    number: null,
    content: null,
    isMenu: false,
    onChangeInputCount: () => {},
    onClickAddBascket: () => {},
};

export default ShopItemDetailInfo;

 

이러한 컴포넌트가 있다고 가정 할 때에 데이터를 보여주는데 이 데이터가 isMenu 에 따라 스타일이 다르게 적용 되게 됩니다. 이때에 기존에 sass 나 css 였다면 서로 다른 클래스를 만들어서 isMenu 에 따라 클래스를 덧붙여주고 떼어주고 해야하는데 styled-component를 사용하게 되면 props를 받아서 스타일링 안에 분기를 가지고 스타일을 적용 시킬 수 있게 됩니다.

 

styled-component를 쓰는 제 수준은 아주 기초적인 수준에 못미치지만 정말 편리하고 유용한것 같습니다.

 

다양한 방법 및 설치는 velog 를 참조 부탁드립니다.

참조: https://velog.io/@velopert/react-component-styling

 

다양한 방식의 리액트 컴포넌트 스타일링 방식 CSS, Sass, CSS Module, styled-components

리액트에서는 컴포넌트를 스타일링 할 때 다양한 방식을 사용 할 수 있습니다. 이 튜토리얼에서는 어떤 방식이 있는지, 자주 사용되는 것들을 하나하나 사용해보겠습니다. 저는 개인적으로 컴포넌트 하나마다 Sass 파일 하나씩 만들어서 관리를 하는것을 선호하고, 최근 만드는 프로젝트에서는 styled-components 를 사용하기도 합니다 :) CSS Mod...

velog.io

 

Comments