styled-components는 <ThemeProvider>라는 컴포넌트를 포함한다. 이 컴포넌트는 컨텍스트 API를 통해 자체 아래의 모든 React 컴포넌트에 테마를 제공한다. 렌더링 트리에서 모든 스타일 컴포넌트는 여러 레벨과 뎁스인 경우에도 테마를 액세스할 수 있다.
const Button = styled.button`
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border-radius: 3px;
color: ${props => props.theme.main};
border: 2px solid ${props => props.theme.main};
`;
// ThemeProvider를 사용할 때 default props를 지정해서 사용할 수도 있다.
Button.defaultProps = {
theme: {
main: "palevioletred"
}
}
const theme = {
main: "mediumseagreen"
};
render (
<div>
<Button>Nomal</Button>
<ThemeProvider theme={theme}>
<Button>Themed</Button>
</ThemeProvider>
</div>
);
테마 props에 함수를 전달할 수도 있다. 이 함수는 부모 테마 안에서 새로운 <ThemeProvider>를 사용해 다른 테마를 받는다. 이런 식으로 테마 자체를 상황에 맞게 만들 수도 있다.
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;
`
const theme = {
fg: "palevioletred",
bg: "white"
};
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>
);
- withTheme
withTheme는 테마 개체에 액세스할 수 있게 해주는 HOC이다. 이 것은 테마에 따라 달라지는 스타일이 있는 컴포넌트를 만들거나 테마 관련 props를 하위 컴포넌트에 전달하려는 경우에 유용하다. 먼저, 전체 앱을 래핑하는 ThemeProvider를 만들고 테마 개체를 제공해야 한다.
import { ThemeProvider } from 'styled-components';
const theme = {
primaryColor: '#006699',
secondaryColor: '#ff9900'
}
const App = () => {
return (
<ThemeProvider theme={theme}>
{/* ... app components /*}
</ThemeProvider>
)
}
그런 다음 스타일이 지정된 컴포넌트에서 withTheme를 사용하여 테마 개체를 액세스할 수 있다.
import styled from 'styled-components'
import { withTheme } from 'styled-components'
const Button = styled.button`
background-color: ${props => props.theme.primaryColor};
color: white;
padding: 10px;
`;
const ThemedButton = withTheme(Button);
const MyComponent = () => {
return (
<div>
<ThemedButton>Click me</ThemedButton>
</div>
)
};
이 코드에서 테마의 primaryColor를 사용하는 Button 컴포넌트를 만든다. 그런 다음 withTheme HOC를 사용하여 테마 개체에 액세스할 수 있는 ThemedButton 컴포넌트를 만든다. 그런 다음 MyComponent 컴포넌트에서 ThemedButton을 사용했다.
- ThemeContext
React의 useContext와 styled-components의 ThemeContext를 사용해서도 이전의 기능을 구현할 수 있다.
import { ThemeProvider } from 'styled-components';
const theme = {
primaryColor: 'blue',
secondaryColor: 'green'
}
function App() {
return (
<ThemeProvider theme={theme}>
<Example>
</ThemeProvider>
)
}
import React, { useContext } from 'react';
import styled, { ThemeContext } from 'styled-components';
const StyledComponent = styled.div`
background-color: ${props => props.theme.primaryColor};
`
const Example = () => {
const themeContext = useContext(ThemeContext);
return <StyledComponent theme={themeContext.theme}>Example</StyledComponent>
}
여기서 StyledComponent는 테마의 primaryColor를 사용하여 배경색을 설정하는 스타일 컴포넌트이다. Example은 useContext를 사용하여 ThemeContext에서 theme 객체를 액세스한 다음 StyledComponent에 props를 전달하는 기능적 컴포넌트이다.
- useTheme
useTheme는 위의 방법을 구현하는 것들 중 가장 최근에 나온 방법이다. hook으로 사용한다.
import { useTheme } from 'styled-components';
const MyComponent = () => {
const theme = useTheme();
return (
<div>
<p>Primary color: {theme.primaryColor}</p>
<p>Secondary color: {theme.secondaryColor}</p>
</div>
)
}
당연히 useTheme 역시 컴포넌트가 ThemeProvider의 자손이어야 한다. 컴포넌트 트리에 ThemeProvider가 없으면 useTheme에서 오류가 발생한다.
마지막으로 테마를 부분적으로만 사용하거나 일부러 피하게도 할 수 있다.
const Button = styled.button`
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border-radius: 3px;
color: ${props => props.theme.main};
border: 2px solid ${props => props.theme.main};
`
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" }}>Overriden</Button>
</div>
</ThemeProvider>
</div>
);
'html&css' 카테고리의 다른 글
[styled-components] animations (0) | 2023.04.04 |
---|---|
[styled-components] Attaching additional props (0) | 2023.04.04 |
[styled-components] pseudoelements, pseudoselectors and nesting (0) | 2023.03.31 |
[styled-components] within a component and outside of the render (0) | 2023.03.31 |
[styled-components] Extending Styles (0) | 2023.03.30 |