학습 키워드
CSS의 문제점을 해결하고자 자바스크립트 코드로 CSS를 작성하는 방식으로 설계
Tagged Template Literals
문법 사용
📖 Tagged Template Literals
ES6에 추가 된 문법으로 template literals 의 더욱 발전된 한 형태로 태그를 사용하면 템플릿 리터럴을 함수로 파싱 할 수 있다. 태그 함수의 첫번째 인수는 문자열 값의 배열을 포함하고, 나머지 인수는 표현식관 관련되어 있다.
⚙️ 설치 및 설정
Copy npm i styled-components
npm i -D @types/styled-components @swc/plugin-styled-components
vscode-styled-components Extention 설치
Copy {
"jsc": {
"experimental": {
"plugins": [
[
"@swc/plugin-styled-components",
{
"displayName": true,
"ssr": true
}
]
]
}
}
}
기본 사용법
sytel.원하는 태그 쓰고 리터널방식으로 css 속성들을 넣어주면 된다.
Copy import React from 'react' ;
import styled from 'styled-components' ;
const Circle = styled . div `
width: 5rem;
height: 5rem;
background: black;
border-radius: 50%;
` ;
function App () {
return < Circle />;
}
export default App;
props
props를 이용해서 활성화 여부를 표현하거나 특정 스타일을 잡아 주고 싶을 때 유용
Copy import { useState } from 'react' ;
import styled , { css } from 'styled-components' ;
type ButtonProps = {
active ?: boolean ;
};
const Button = styled . button < ButtonProps > `
width: 100px;
height: 100px;
background-color: #fff;
color: #000;
border: 1px solid gray;
${ (props) =>
props .active &&
css `
background-color: #00f;
color: #fff;
border: 1px solid #00f;
` }
` ;
export default function Switch () {
const [ toggle , setToggle ] = useState ( false );
const handleClick = () => {
setToggle ( ! toggle);
};
return (
< Button onClick = {handleClick} active = {toggle}>
ON/OFF
</ Button >
);
}
attrs
기본 속성을 추가할 수 있다. 불필요하게 반복되는 속성을 처리할 때 유용
Copy import styled , { css } from 'styled-components' ;
type ButtonProps = {
type ?: 'button' | 'submit' | 'reset' ;
};
const Button = styled . button .attrs < ButtonProps >((props) => {
return {
type : props .type ?? 'button' ,
};
}) `
width: 100px;
height: 100px;
background-color: #fff;
color: #000;
border: 1px solid gray;
` ;
export default Button
Reset CSS
styled-components 에서 Reset CSS 처럼 태그들의 기본 속성을 초기화 하기 위해 설치
Copy // App.tsx
import { Reset } from 'styled-reset' ;
export default function App () {
return (
< div >
< Reset />
</ div >
);
}
Global Style
styles
폴더 , GlobalStyle.ts
파일 생성
Copy mkdir styles
touch styles/GlobalStyle.ts
Copy // GlobalStyle.ts
import { createGlobalStyle } from 'styled-components' ;
const GlobalStyle = createGlobalStyle `
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
html {
font-size: 62.5%;
}
body {
font-size: 1.6rem;
}
:lang(ko) {
h1, h2, h3 {
word-break: keep-all;
}
}
` ;
export default GlobalStyle
Copy import { Reset } from 'styled-reset' ;
import GlobalStyle from '../styles/GlobalStyle' ;
export default function App () {
return (
< div >
< Reset />
< GlobalStyle />
</ div >
);
}
Theme
styles/defaultTheme.ts
파일 생성
Copy const defaultTheme = {
colors : {
background : '#FFF' ,
text : '#000' ,
primary : '#F00' ,
secondary : '#00F' ,
} ,
};
export default defaultTheme;
역으로 typeof
를 사용해서 Theme 타입 지정 → styles/Theme.ts
파일 생성
Copy import defaultTheme from './defaultTheme' ;
type Theme = typeof defaultTheme;
export default Theme;
styles/darkTheme.ts
파일 생성해서 Theme 으로 타입 지정
Copy import Theme from './Theme' ;
const darkTheme : Theme = {
colors : {
background : '#000' ,
text : '#FFF' ,
primary : '#F00' ,
secondary : '#00F' ,
} ,
};
export default darkTheme;
최상위 <ThemeProvider>
컴포넌트를 통해 공급
Copy import { Reset } from 'styled-reset' ;
import { ThemeProvider } from 'styled-components' ;
import GlobalStyle from '../styles/GlobalStyle' ;
import defaultTheme from '../styles/defaultTheme' ;
import Greeting from './components/Greeting' ;
import Switch from './components/Switch' ;
export default function App () {
const theme = defaultTheme;
return (
< ThemeProvider theme = {theme}> { /* 👈🏻 Theme 공급 */ }
< Reset />
< GlobalStyle />
< Greeting />
< Switch />
</ ThemeProvider >
);
}
공급 받은 theme을 사용하기 위해선 타입 지정 필요 → styled.d.ts
파일 생성
아래 코드 처럼 하나씩 지정해줘도 되지만, 속성들이 추가될 가능성을 고려해서 Theme.ts
활용
Copy import 'styled-components' ;
declare module 'styled-components' {
export interface DefaultTheme extends Theme {
colors : {
background : string ;
text : string ;
primary : string ;
secondary : string ;
}
}
}
또는
Copy import 'styled-components' ;
import type Theme from './Theme' ;
declare module 'styled-components' {
export interface DefaultTheme extends Theme {}
}
📌 Theme 의미 있게 사용하기 위해 참고
🚨 window.matchMedia
Error 발생
Jest 테스트에서 다크모드 구현시 window.matchMedia
Error 발생
window.matchMedia
는 사용자의 시스템 설정의 테마를 인식하기 위해 사용한다.
Jest 공식문서에는 src/setupTests.ts
파일 해당 코드 사용해서 이슈를 해결하라고 안내하고 있다.
Copy // src/setupTests.ts
Object .defineProperty (window , 'matchMedia' , {
writable : true ,
value : jest .fn () .mockImplementation (query => ({
matches : false ,
media : query ,
onchange : null ,
addListener : jest .fn () , // deprecated
removeListener : jest .fn () , // deprecated
addEventListener : jest .fn () ,
removeEventListener : jest .fn () ,
dispatchEvent : jest .fn () ,
})) ,
});
🔗 참고
Last updated 6 months ago