일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 슬라이드전환
- 깃
- 프론트엔드
- 타입스크립트
- git
- 연산자
- PROJECT
- 웹디자인기능사
- 웹디자인기능사실기
- 실기
- HTML
- jQuery
- 비전공자
- CSS
- 리액트
- 정보처리기사
- 세로메뉴바
- Supabase
- 웹퍼블리셔
- 자바스크립트
- 생활코딩
- 렛츠기릿자바스크립트
- react
- github
- 코드공유
- JavaScript
- web
- 코딩독학
- JS
- 웹디실기
- Today
- Total
코딩하는라민
[React+TS] Styled-components 전역 theme 적용하기 본문
[React+TS] Styled-components theme 적용하기
이전 프로젝트들은 GlobalStyle 에 `:root` 를 이용해 테마 색상을 정의해서 사용했다. styled-components 에도 이러한 기능이 내장되어 있어 사용해보고자 한다.
styled-components 는 `ThemeProvide` 라는 컴포넌트를 제공한다. 이 컴포넌트는 theme 라는 props 에 theme 정보들을 넘겨받아 하위 컴포넌트들에 그 정보들을 사용할 수 있게 해준다.
ThemeProvide 이 `Context API` 기반으로 만들어졌기 때문에 가능하다. 즉, Context API 를 통해 여러 하위 컴포넌트들이 Theme 정보에 접근할 수 있도록 해주는 원리이다.
Theme 정보 생성하기
styled.d.ts 에 테마에 대한 타입 선언
src/styles 디렉토리에 styled.d.ts 파일을 생성해준다.
- declare module 'styled-components' : 모듈을 확장하여 타입스크립트가 사용자가 정의한 속성을 추가할 수 있도록 해준다.
- interface DefaultTheme : DefaultTheme 인터페이스는 styled-component 라이브러리에서 제공된다. DefaultTheme 인터페이스를 확장하여 사용자 정의 속성을 추가할 수 있다.
import 'styled-components'
declare module 'styled-components' {
export interface DefaultTheme {
color: {
main: string
sub: string
white: string
}
}
}
theme.ts 에 사용할 테마 정보 정의
다음으로 src/styles 디렉토리에 Theme.ts 파일을 생성한다.
- styled-components 에서 제공하는 DefaultTheme 을 가져와 우리가 정의해줄 theme 의 타입으로 지정해준다.
- DefaultTheme 에는 우리가 정의해준 사용자 정의 속성 color 의 실제 값들을 입력해준다.
- colors 의 각 키 값들은 string 타입으로 `문자열` 형태로 적어준다.
import { DefaultTheme } from 'styled-components'
export const theme: DefaultTheme = {
color: {
main: '#3c5afe',
sub: '#ff6e40',
white: '#ffffff'
}
}
`<ThemeProvider>` 적용하기
- Theme 적용할 컴포넌트를 styled-components 에서 제공하는 `ThemeProvider` 컴포넌트로 감싸준다.
- ThemeProvider 의 props 로 아까 정의해준 Theme 를 가져와서 전달해준다.
import { ThemeProvider } from 'styled-components'
import { theme } from '@/styles/theme'
ReactDOM.createRoot(document.getElementById('root')!).render(
<ThemeProvider theme={theme}>
<GlobalStyle />
<RouterProvider router={router} />
</ThemeProvider>
)
이제 하위 컴포넌트들에도 props 로 theme 가 적용된다.
Theme 사용하기
스타일드 컴포넌트 내부에서 사용하기
스타일드 컴포넌트 안에서 `props.theme` 의 형태로 우리가 사용자 정의 속성으로 추가해준 객체들을 꺼내 사용할 수 있다.
const Container = styled.div`
background: ${props => props.theme.color.main};
color: ${props => props.theme.color.white};
`
구조분해할당으로 더 간단하게 표현하면 아래와 같다.
const Container = styled.div`
background: ${({ theme }) => theme.color.main};
color: ${({ theme }) => theme.color.white};
`
스타일드 컴포넌트 외부에서 사용하기
스타일드 컴포넌트가 아닌 외부에서 theme 를 사용하려고 하면 props.theme 가 가져와지지 않는다.
이 theme 는 스타일드 컴포넌트에서만 상속되는 속성이기 때문이다.
따라서 외부에서 theme 를 가져오기 위해서는 `useTheme` 훅이나 `withTheme` HOC 를 사용해야한다.
useTheme Hook 사용하기
import { useTheme } from 'styled-components'
const Header = () => {
const theme = useTheme()
console.log(theme.color.white) // ✅ '#ffffff'
return (
...
)
}
구조분해할당으로 더 간단하게 표현하면 아래와 같다.
import { useTheme } from 'styled-components'
const Header = () => {
const { color } = useTheme()
console.log(color.white) // ✅ '#ffffff'
return (
...
)
}
withTheme HOC 사용하기
import { withTheme } from 'styled-components';
const Header = ({ theme }) => (
console.log(theme.color.white) // '#ffffff'
return (
...
)
);
// withTheme HOC를 통해 테마를 전달
const AppWithTheme = withTheme(Header);
Theme Props 를 함수에 전달하여 Theme Function 으로 사용하기
- Theme 를 정의해준 뒤,
- invertTheme 에 Theme 의 색상을 반전하여 정의해준다.
- invertTheme 를 theme 대신 ThemeProvider 컴포넌트에 전달해주면 하위 컴포넌트에서 메인 색상과 반전된 색상을 가져와 사용할 수도 있다.
// Define our `fg` and `bg` on the theme
const theme = {
fg: "#BF4F74",
bg: "white"
};
// This theme swaps `fg` and `bg`
const invertTheme = ({ fg, bg }) => ({
fg: bg,
bg: fg
});
render(
<ThemeProvider theme={theme}>
<div>
<Button>Default Theme</Button>
<ThemeProvider theme={invertTheme}>
<Button>Inverted Theme</Button>
</ThemeProvider>
</div>
</ThemeProvider>
);
styled.d.ts 의 복잡해진 타입 간단하게 정의하기
theme 에 정의한 속성들이 많아지면 타입을 일일이 지정해주기 번거로워진다.
- theme.ts 파일로 가서 우리가 정의해준 color 에 `typeof` 연산자를 통해 객체 타입으로 변환해준다.
- 이때 color 속성은 바깥으로 따로 꺼내어 정의해준다.
import { DefaultTheme } from 'styled-components'
const color = {
main: '#3c5afe',
sub: '#ff6e40',
white: '#ffffff'
}
export type ColorTypes = typeof color
export const theme: DefaultTheme = {
color
}
`typeof` 연산자는 피연산자의 평가 전 자료형을 나타내는 문자열을 반환한다.
즉, `typeof` 를 통해 우리가 직접 값으로 정의한 color 객체의 타입을 자동으로 가져올 수 있는 것이다.
- 이제 이렇게 추출한 타입을 styled.d.ts 로 가져와서 color 에 타입을 지정해주면 된다.
import 'styled-components'
import { ColorTypes } from '@/styles/theme'
declare module 'styled-components' {
export interface DefaultTheme {
color: ColorTypes
}
}
참고
'Styling > Styled-Components' 카테고리의 다른 글
[React] Styled Component (CSS-in-JS) (2) | 2023.03.13 |
---|