Styled Components Theme

김동현·2023년 4월 21일
0

Styled Components

목록 보기
2/2

Theming

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>
);

결과화면

Function themes

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>
);

결과화면

Getting the theme without styled components

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)
  // ...
}

The theme prop

다 필요없고, 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>
);

결과화면

[참고]: 스타일 컴포넌트 공식 홈페이지

profile
프론트에_가까운_풀스택_개발자

0개의 댓글