본문 바로가기
React

[React] Css in js / Styled.component

by 리슨업 2024. 2. 3.

 

#1. Css-in-js / Styled.component 이거 왜 씀?

 

 

처음에 난 이거 왜 쓰는지 정말 몰랐다.

동적으로 스타일을 변경할때 쓰인다고 익히 들었지만 그것도 modules.css로 가능한것이었으니까 예로 

import classes from '경로';
<div className={isActive ? classes.Active : undefined }>hello world</div>

이런식으로도 충분하게 가능한 부분이어서 별 필요성을 못느끼던 찰나

 

컴포넌트에서 props로 전달하고 그 props의 값을 이용해서 css in js의 스타일을 변경 할 수 있다는 것을 발견..

이는 굳이 상태 훅이나 따로 만들 필요없이 컴포넌트 내에서 css in js도 같은 props를 이용해서 css가 동적 할당이 가능하라는 뜻이다 (직관적이라는 뜻.)

 

이는 불필요한 로직이 필요가 없어지며, 또 내가 직접 클래스을 인에이블, 언에이블 명을 정하지 않아도 되는 작명의 고통에서 벗어 날 수 있다.

 

 

일반 HTML이라면 CSS는 DOM트리를 기준으로 랜더링을 구성하지만 React는 좀 다르다. 

 

 

[HTML의 Style Sheet 생명주기]

1. HTML DOM트리 구성 

2. CSS 로딩 _ ( HTML 요소에 어떠한 스타일을 적용할지 정의함 )

3. CSS 랜더링 트리 구성 _ ( HTML DOM트리에 따라 적용할 CSS의 랜더링 트리 구성)

3. Css 랜더링 트리 구성 > Paint _ ( 이 단계에 스타일이 반영되며 화면 출력함  )

 

[React 생명주기 ]

1. 함수컴포넌트 호출 useState , useQuery , useRef 등.. Hook 실행  _ ( useEffect 은 마지막에 실행) 

2. 함수와 Hook의 구성을 통해서 가상 DOM 생성

3. Css-in-js 호출 JavaSciprt를 Css로 랜더링 

    ( <head></head>안으로 <style>태그의 형태로 동적 삽입 )

 

4. JSX 스타일 할당 _ ( 이 시점에 css가 JSX 요소에 할당 )

5. 가상DOM을 사용하여 실제  DOM 랜더링  _ ( useEffect"마운트" 되는 시점인 랜더링 이후에 실행 ) 

 

 

Css in js 는 JavaScript를 거쳐서 Css가 할당되며, 훅이 재 실행되면 재 랜더링이 되기에 매번 JavaSciprt에서 css로 변환해야 한다. 이런 이유로  일반 css보다 성능면으로 안 좋을 수 있다.

 

 

 

#2. CSS-in-js 사용법

css-in-js 설치와 필요한 컴포넌트에서 import 해주자 

npm install styled-components
import styled from 'styled-components'; // 스타일 컴포넌트 임포트

 

 

 

[예시1] button에 색상 입히기

const Mybutton = styled.button`
    background: rgba(255,255,255,.7);
    color: #fff;
`
return(
    <>
		<Mybutton/> 
    </>
)

간단한 button에 색상을 입히는 로직이다

styled.[element] 은 만들어질 element를 정의한다. styled.div, styled.li 이렇게 구성했다면 <div></div> <li></li> 형식으로 구성이 될 것이다. 

 

 

 

 

[예시2] button에 prop로 동적 스타일 할당

const Mybutton = styled.button`
    background: rgba(255,255,255,.7);
    color: #fff;
    ${props => props.$visible && `color:blue`}
`

export default function Component(){
	const [ visible , setVisible ] =useState(false);

    return(
        <>
            <Mybutton
                onClick={()=>setVisible(prev => !prev)}
                $visible={visible}
            /> 
        </>
    )
}

보면 visible이라는 상태를 props로 전달해서 css in js 글씨 색상을 변경하고 있다. 

한 스코프 내에서 props의 상태로 어떻게 css가 변경되는지 직관 적으로 확인 할 수 있다라는 점이 가장 큰 핵심이다.

 

 

 

 

[예시3] 외부 컴포넌트 스타일링

// OutsideComponent.js
export default function OutsideComoponent({className , children , ...props}){
	return(
    	<>	
        	<p>외부 컴포넌트!</p>
        	<div className={className} {...props}>{children}<div>
        </>
    )
}


// InsideComponent.js
import React, { useState } from 'react';
import styled from 'styled-components';
import OutsideComponent from './OutsideComponent';

const MyButton = styled(OutsideComponent)`
  background: rgba(255, 255, 255, 0.7);
  color: #fff;
  ${props => props.$visible && `color: blue;`}
`;

export default function Component() {
  const [visible, setVisible] = useState(false);

  return (
    <>
      <MyButton onClick={() => setVisible(prev => !prev)} $visible={visible}>
        내부 컴포넌트!
      </MyButton>
    </>
  );
}

 

css in js에서 스타일링 된 스타일들은 "className"으로 전달된다. class의 명이 곧  style 이기 때문에..

이렇게 className으로 매핑된 style들은 동적으로 삽입이 가능하고, 물론 onClick 또한 props로 '프롭스 드릴링' 형태가 되어 

onClick으로 상위 컴포넌트인 setVisible을 핸들링 할 수 있다. _("styeld(컴포넌트)" 는 외부의 컴포넌트를 사용할때 주로 사용 )

 

 

 

 

 

#3. Css in js 사용 간에 이슈사항

React는 컴포넌트에 선언된 props들을 통해 전달 된 Props(attribute)를 통해 컴포넌트를 구성한다.

Css-in-JS또한 attribute를 의존하여 스타일을 변경하기에 보통 boolean 값을 이용해서 true, false값으로 를 판가름하여 스타일을  동적 반영한다. 

const [ visible, setVisible ]  = useState(false);
const Component = Styled.div`
	${props => props.visible && 'color: red'} 

`
<Component visible={visible}>Hello world</Component>

 

매우 유용하게 사용하지만 문제점이 있었다. 

여기서 상태 훅을 이용해서 visible값을 전달하는데 Component에 visible={visible} 을 전달하여 스타일 적용하는 것까진 문제 없었다.

 

Css in js를 사용하다보면 자주 발생하는 이슈로 DOM에 직접 정의되지 않는 attribute에 값을 blooean으로 반영 하기 때문에 발생되는 오류였다. 

 

이를 "transient props" 라는 "$" 접두사를 붙이게되면 오류를 막을 수 있었다.

props.$visible / $visible={visible}