styled-components는 <ThemeProvider>
래퍼 컴포넌트를 exporting 함으로써 full theming을 지원한다.
<ThemeProvider>
컴포넌트는 context api를 통해 아래의 모든 리액트 컴포넌트에 theme를 제공한다.
// Define our button, but with the use of props.theme this time
const Button = styled.button`
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border-radius: 3px;
/* Color the border and text with theme.main */
color: ${props => props.theme.main};
border: 2px solid ${props => props.theme.main};
`;
// We are passing a default theme for Buttons that arent wrapped in the ThemeProvider
Button.defaultProps = {
theme: {
main: "palevioletred"
}
}
// Define what props.theme will look like
const theme = {
main: "mediumseagreen"
};
render(
<div>
<Button>Normal</Button>
<ThemeProvider theme={theme}>
<Button>Themed</Button>
</ThemeProvider>
</div>
);
theme prop에 함수를 전달할 수 도 있다.
이 함수는 트리 구조상 부모에 위치한 <ThemeProvider>
가 제공하는 parent theme을 인자로 전달받는다.
// Define our button, but with the use of props.theme this time
const Button = styled.button`
color: ${props => props.theme.fg};
border: 2px solid ${props => props.theme.fg};
background: ${props => props.theme.bg};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border-radius: 3px;
`;
// Define our `fg` and `bg` on the theme
const theme = {
fg: "palevioletred",
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>
);
via withTheme higher-order component
withTheme은 styled-components에서 제공하는 고차 컴포넌트(Higher-Order Component)이다.
withTheme을 사용하면 ThemeProvider로 전달된 테마 객체를 컴포넌트의 props로 전달할 수 있다.
import { withTheme } from 'styled-components';
const MyComponent = ({ theme }) => (
<div>
<p>Primary color: {theme.primaryColor}</p>
<p>Secondary color: {theme.secondaryColor}</p>
</div>
);
export default withTheme(MyComponent);
이렇게 하면 MyComponent에서 theme props를 사용할 수 있다.
이 props를 사용하면 ThemeProvider에서 전달한 테마 객체를 사용할 수 있다.
via useContext React hook
또한 useContext
를 사용하여 현재 theme에 액세스할 수 있다.
import { useContext } from 'react'
import { ThemeContext } from 'styled-components'
const MyComponent = () => {
const themeContext = useContext(ThemeContext)
console.log('Current theme: ', themeContext)
// ...
}
via useTheme custom hook
또한 useTheme
를 사용해서도 액세스 가능하다.
import { useTheme } from 'styled-components'
const MyComponent = () => {
const theme = useTheme()
console.log('Current theme: ', theme)
// ...
}
다 필요없고, theme을 직접 prop으로 전달할 수도 있다.
ThemeProvider이 누락되는 걸 방지하거나 theme을 오버라이딩 할 때 사용한다.
// Define our button
const Button = styled.button`
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border-radius: 3px;
/* Color the border and text with theme.main */
color: ${props => props.theme.main};
border: 2px solid ${props => props.theme.main};
`;
// Define what main theme will look like
const theme = {
main: "mediumseagreen"
};
render(
<div>
<Button theme={{ main: "royalblue" }}>Ad hoc theme</Button>
<ThemeProvider theme={theme}>
<div>
<Button>Themed</Button>
<Button theme={{ main: "darkorange" }}>Overridden</Button>
</div>
</ThemeProvider>
</div>
);
[참고]: 스타일 컴포넌트 공식 홈페이지