이모션이란, CSS in JS 형식으로, Javascript 파일 안에서 CSS를 설정할 수 있는 라이브러리 입니다. 왜 이걸 하냐면, React의 경우 자바스크립트로 (코드, CSS, HTML) 모든 것을 한번에 하는 것이 이상적인데 Html 태그안에 넣어서 css를 지정하는 in-line css를 사용하면 리랜더링 될 때마다 다시 새롭게 메모리를 쓰는데, 이모션같은 라이브러리를 쓰면 그럴일이 없다는 사실..!
뭐 그외에도 변수사용이나, Props 사용 과 같은 상태 에 따른 css를 쉽게 해주기 때문에 사용 된다.
타입스크립트와 이모션을 사용할 때 한가지 주의할 점이 있는데, emotion-theming
기능을 사용하며 Emotion/styled
를 사용할때 styled
내부안에서 color : ${props => props.theme.textColor}
을 하게 되면 textColor
를 못 찾아서 오류가 뜨게 된다. 그 이유는 styled
의 props.theme
의 타입이 object 로만 되어 있어서 theme.something
을 못찾게 되는 것이다. 그래서 그 type을 바꿔주면 되는데, 공식문서를 찾아가서 바꾸는 게 이 방법이다.
import styled, { CreateStyled } from '@emotion/styled'
export type themeType = {
...
color : string;
background : string;
textColor : string;
boxShadow : string;
darkMode : boolean;
...
}
export default styled as CreateStyled<themeType>
쓰고 싶은 타입을 재 지정해서 export
해서 이것을 emotion/styled
대신에 쓰는 방법이다.
아마 emotion/styled
을 사용하지 않고 다른 방법으로 emotion
을 쓰면 이러한 오류는 안나오는 것으로 알고 있다.
뭐 이런 저런 사용법은 건너뛰고 ThemeProvider를 이용한 테마기능을 사용해보자.
// ThemeProviderContainer.tsx
import { ThemeProvider } from 'emotion-theming'
...
const theme = {
color : isDarkMode ? black : white,
background : isDarkMode ? "rgba(20, 20, 20, 0.7)" : "rgba(230, 230, 230)",
textColor : isDarkMode ? white : black,
boxShadow : isDarkMode ? 'rgba(230, 230, 230, 0.3)' :'rgba(20, 20, 20, 0.3)',
darkMode : isDarkMode
}
...
return (
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
)
이렇게 하면 하위 컴포넌트에 theme이 전달이 된다.
하위 컴포넌트에서는 그냥
const Main = styled.main`
width : 100vw;
height : 100vh;
font-family : sans-serif;
background-color :${props => props.theme.background};
color :${props => props.theme.textColor};
${props.theme}
의 형식으로 찾아다니면 된다
타입을 새로 지정해서 보내준 것이 바로 뜬다.
또한, useTheme()
함수가 제공되는데 이 함수는 ThemeProvider
의 theme
으로 받은 것을 전역상태로 관리 할 수 있는 것 이다.
const theme = useTheme() as any;
타입을 지정해주지 않으면 unknown 타입인데, 이러면 theme 객체를 사용하면 오류가 뜬다. theme.color // 오류 발생
theme
은 전역상태이기 떄문에 이것을 받아 컴포넌트 여기저기 상태를 바꿔주면 된다.
로컬스토리지에 key : dark, value : {value : boolean }
을 넣어줄 것이다.
ThemeProvider
에서는 JSON.parse(localstorage.getItem('dark')).value
를 해서 정보를 받는다.localstorage.setItem('dark', JSON.stringify({ value : !theme.darkMode }))
를 해준다.
useTheme사용할 때 emotion.d.ts파일로 theme타입을 declare moudle사용해서 재정의 해주면 사용가능해져요!