📌 이 글은 emotion 공식문서의 Best Practices 참고하여 작성되었습니다.
어떤 애플리케이션을 개발하는데 에러메세지 스타일이 여러 컴포넌트에서 반복적으로 사용되며, 해당 에러메세지는 폰트사이즈가 다른 여러버전이 존재한다고 가정해봅시다.
이러한 스타일을 재사용하기 위해 스타일을 공유하는 방법은 두가지가 있습니다.
export const errorCss = css({
color: 'red',
fontWeight: 'bold'
})
// Use arrays to compose styles
export const largeErrorCss = css([errorCss, { fontSize: '3rem' }])
export const mediumErrorCss = css([errorCss, { fontSize: '2rem' }])
export const smallErrorCss = css([errorCss, { fontSize: '0.5rem' }])
import { errorCss, largeErrorCss, mediumErrorCss , smallErrorCss} from '...'
return (
<p css=[errorCss, {fontSize: '5rem'}]>Failed!!!!!!!</p>
<p css={largeErrorCss}>Failed!!!</p>
<p css={mediumErrorCss}>Failed!!</p>
<p css={smallErrorCss}>Failed!</p>
)
아래처럼 컴포넌트 자체를 재사용 해줄 경우 좀 더 반복적이 코드를 줄일 수 있습니다.
export function ErrorMessage({ className, children }) {
return (
<p css={{ color: 'red', fontWeight: 'bold' }} className={className}>
{children}
</p>
)
}
export function LargeErrorMessage({ className, children }) {
return (
<ErrorMessage css={{ fontSize: '3rem' }} className={className}>
{children}
</ErrorMessage>
)
}
📌 css={}로 넘긴 css object는 하위컴포넌트의
className
으로 넘어감
import { ErrorMessage, LargeErrorMessage} from '...'
return (
<ErrorMessage css={{ fontSize: '5rem' }}>Failed!!!!!!!</ErrorMessage>
<LargeErrorMessage>Failed!!!</LargeErrorMessage>
만약 다른 스타일은 동일하지만 backgroud-style만 달라지는 경우에 어떻게 구현할 수 있을까요?
만약 동적으로 스타일을 줄 수 없다면 아래와 같이 중복되는 코드를 계속해서 작성해야 할 것입니다.
<style>
.css-1udhswa {
border-radius: 50%;
width: 40px;
height: 40px;
background-style: url(https://i.pravatar.cc/150?u=0);
}
.css-1cpwmbr {
border-radius: 50%;
width: 40px;
height: 40px;
background-style: url(https://i.pravatar.cc/150?u=1);
}
.css-am987o {
border-radius: 50%;
width: 40px;
height: 40px;
background-style: url(https://i.pravatar.cc/150?u=2);
}
</style>
이를 style props를 사용한다면 쉽게 해결 할 수 있습니다.
1. style
코드에서는 var(변수명)
형태로 사용
2. element
에서는 style={{'변수명' : 값}}
으로 넘겨주면 됩니다.
.avatar {
border-radius: 50%;
width: 40px;
height: 40px;
background-style: var(--background-style);
}
function Avatar({ imageUrl }) {
return <div className="avatar" style={{ '--background-style': imageUrl }} />
}
만약 typescript를 사용한다면 style={{ ['--background-style' as any]: imageUrl }} 이렇게 사용해주면 된다.
dark mode, light mode를 개발하는 방법중에 emotion의 ThemeProvider을 사용하는 방법이 있습니다.
import { ThemeProvider } from '@emotion/react'
const theme = {
colors: {
primary: 'hotpink'
}
}
render(
<ThemeProvider theme={theme}>
<App.js>
</ThemeProvider>
)
import {useTheme } from '@emotion/react'
const theme = {
colors: {
primary: 'hotpink'
}
}
function SomeText(props) {
const theme = useTheme()
return <div css={{ color: theme.colors.primary }} {...props} />
}
import {useTheme } from '@emotion/react'
const theme = {
colors: {
primary: 'hotpink'
}
}
function SomeText(props) {
return <div css={theme => ({ color: theme.colors.primary })}>some other text</div>
}
ThemeProvider는 Context API로 전체 테마를 바꾸는 것입니다. 그런데 이는 CSS 변수 접근 방식과 비교하면 아래의 두가지 단점이 존재합니다.
1. DX 하락: 코드가 복잡해짐
2. 성능 하락: ThemeProvider 접근 방식을 사용하면 모든 구성 요소의 스타일을 업데이트해야 하며 브라우저는 해당 업데이트를 페인트함, 그러나 CSS 변수 접근 방식을 사용하면 스타일을 단일 구성 요소(본문)로 업데이트한 다음 브라우저에서 해당 업데이트를 페인트함