styled-components

2021-08-01 hit count image

react-native 스타일링을 위해 styled-components 라이브러리를 활용하는 방법에 대해 알아보자.

react-native 프로젝트 생성

TypeScript를 적용한 프로젝트에서 진행합니다. RN에 TypeScript를 적용하는 방법은 이전 블로그를 참고하세요.

styled-components 라이브러리 설치

styled-components 라이브러리와 TypeScript 연동을 위한 라이브러리를 설치합니다.

npm install --save styled-components
npm install --save-dev babel-plugin-styled-components @types/styled-components @types/styled-components-react-native
  • styled-components: styled-components 라이브러리입니다.
  • @types/styled-components: TypeScript에 필요한 styled-components의 타입입니다.
  • babel-plugin-styled-components: 필수는 아니지만 디버깅시 class명을 확인하기 쉽게 만들어 줍니다. babel.config.js에 아래와 같이 설정해 줍니다.
module.exports = {
  ...
  plugins: ['babel-plugin-styled-components'],
};

사용법

styled-components는 전체 스타일을 관리하기 위한 theme 기능을 제공합니다. theme을 사용하는 방법과 기본적인 사용법을 알아봅니다.

Class Components에서 기본 사용법

  • 기본 스타일 적용
// src/App.tsx
...
import styled from 'styled-components/native';
...
const Container = styled.View`
  flex: 1;
  justify-content: center;
  align-items: center;
  background-color: #f5fcff;
`;
const MainText = styled.Text`
  font-size: 20px;
  text-align: center;
  margin: 10px;
  color: red;
`;
...
interface Props {}
interface State {}
export default class App extends React.Component<Props, State> {
  render() {
    return (
      <Container>
        <MainText>Hello world</MainText>
      </Container>
    );
  }
}
  • props를 이용해 동적으로 스타일 적용
// src/App.tsx
...
import styled from 'styled-components/native';
...

interface IContainerProps {
  background: string;
}

const Container = styled.View`
  flex: 1;
  justify-content: center;
  align-items: center;
  background-color: ${(props:IContainerProps) => props.background ? props.background : 'white'};
`;
const MainText = styled.Text`
  font-size: 20px;
  text-align: center;
  margin: 10px;
  color: red;
`;
...
interface Props {}
interface State {}
export default class App extends React.Component<Props, State> {
  render() {
    return (
      <Container background="red">
        <MainText>Hello world</MainText>
      </Container>
    );
  }
}

Class Components에서 Theme 사용법

공식 사이트에는 TypeScript를 이용하여 theme을 사용하는 방법이 자세히 나와있습니다.

공식 사이트와 예제 사이트를 참고하면 styled-components를 사용하기 위해서는 상대 경로로 지정해야하는 문제가 있다.

그래서 우리는 공식 사이트 방식이 아닌 “props를 이용해 동적으로 스타일 적용” 방법을 응용해서 사용합니다.

  • src/@types/index.d.ts 파일
// src/@types/index.d.ts
interface ITheme {
  color: {
    white: string;
    black: string;
  };
  fonts: {
    normal: string;
  };
}
  • src/Theme.tsx 파일
// src/Theme.tsx
export default {
  color: {
    white: '#FFFFFF',
    black: '#000000',
  },
  fonts: {
    normal: '14px',
  },
};
  • src/App.tsx 파일
...
// src/App.tsx
import { ThemeProvider } from 'styled-components';
import styled from 'styled-components/native';
import Theme from './Theme';
...

interface IContainerPorps {
  theme?: ITheme;
}

const Container = styled.View`
  flex: 1;
  justify-content: center;
  align-items: center;
  background-color: ${(props:IContainerProps) => props.theme && props.theme.color.black};
`;
const MainText = styled.Text`
  font-size: 20px;
  text-align: center;
  margin: 10px;
  color: red;
`;
...
interface Props {}
interface State {}
export default class App extends React.Component<Props, State> {
  render() {
    return (
      <ThemeProvider theme={Theme}>
        <Container>
          <MainText>Hello world</MainText>
        </Container>
      </ThemeProvider>
    );
  }
}

Function Components에서 기본 사용법

import React from 'react';
import styled from 'styled-components/native';

const Container = styled.View`
  flex: 1;
  justify-content: center;
  align-items: center;
  background-color: #f5fcff;
`;
const MainText = styled.Text`
  font-size: 20px;
  text-align: center;
  margin: 10px;
  color: red;
`;

interface Props {}
const App = ({}: Props) => {
  return (
    <Container>
      <MainText>Hello world</MainText>
    </Container>
  );
};

export default App;

Function Components에서 Theme 사용법

import React from 'react';
import styled from 'styled-components/native';
import {ThemeProvider} from 'styled-components';
import Theme from './Theme';

interface StyledProps {
  theme: ITheme;
}
const Container = styled.View`
  flex: 1;
  justify-content: center;
  align-items: center;
  background-color: ${(props: StyledProps) =>
    props.theme && props.theme.color.black};
`;
const MainText = styled.Text`
  font-size: 20;
  text-align: center;
  margin: 10px;
  color: red;
`;

interface Props {}
const App = ({}: Props) => {
  return (
    <ThemeProvider theme={Theme}>
      <Container>
        <MainText>Hello world</MainText>
      </Container>
    </ThemeProvider>
  );
};

export default App;

참고

제 블로그가 도움이 되셨나요? 하단의 댓글을 달아주시면 저에게 큰 힘이 됩니다!

책 홍보

스무디 한 잔 마시며 끝내는 React Native 책을 출판한지 벌써 2년이 다되었네요.
이번에도 좋은 기회가 있어서 스무디 한 잔 마시며 끝내는 리액트 + TDD 책을 출판하게 되었습니다.

아래 링크를 통해 제가 쓴 책을 구매하실 수 있습니다.
많은 분들에게 도움이 되면 좋겠네요.

스무디 한 잔 마시며 끝내는 React Native, 비제이퍼블릭
스무디 한 잔 마시며 끝내는 리액트 + TDD, 비제이퍼블릭
Posts