본문 바로가기
Hybrid/React Native

리액트 네이티브] 11. 스타일드 컴포넌트

by 김마리님 2023. 1. 30.

기본 리액트 네이티브의 CSS는 기존 CSS와 차이가 크다. 단위가 생략된다던지.. 파라메터를 카멜 표기법으로 작성해야한다던지..

이런 부분때문에 '스타일드 컴포넌트'를 이용해 기존 CSS처럼 사용할 수 있다.

 

다음 명령어를 통해 스타일드 컴포넌트를 설치한다.

npm install styled-components

혹은

yarn add styled-components

 

이제 스타일드 컴포넌트를 이용하여 스타일을 적용해보자.

다음과 같은 방식으로 사용할 수 있다.

const Container = styled.View`
    flex: 1;
    background-color: #ffffff;
    align-items: center;
    justify-content: center;
`;

기존 방식과 비교해보자.

const style = StyleSheet.create({
    container : {
        flex : 1,
        backgroundColor : '#fff',
        alignItems : 'center',
        justifyContent : 'center',
    },
}

 

꽤 많이 달라진 것이 보인다.

 

1. 스타일 컴포넌트의 기본

 

이제 실제 적용한걸 보자.

먼저 버튼 요소를 선언하고

 

- ../component/Button.js

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

const ButtonContainer = styled.TouchableOpacity`
  background-color: #9b59b6;
  border-radius: 15px;
  padding: 15px 40px;
  margin: 10px 0px;
  justify-content: center;
`;
const Title = styled.Text`
  font-size: 20px;
  font-weight: 600;
  color: #fff;
`;

const Button = props => {
  return (
    <ButtonContainer>
      <Title>{props.title}</Title>
    </ButtonContainer>
  );
};

export default Button;

 

- .../src/App.js

import React from "react";
import styled from "styled-components/native";
import Button from "../component/Button";


const Container = styled.View`
    flex: 1;
    background-color: #ffffff;
    align-items: center;
    justify-content: center;
`;

const App = () => {
    return (
        <Container>
            <Button title="Mary"/>
            <Button title="React Native"/>
        </Container>
    );
};

 

스타일드 컴포넌트로 지정했을 때도 CSS가 들어가는 모습을 볼 수 있다.

 

 

2. props

 

props에 따라 스타일을 변경할수도 있다.

 

- ../component/Button.js

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

const ButtonContainer = styled.TouchableOpacity`
  background-color: ${props => props.title === 'Mary' ? '#3498db' : '#9b59b6' };
  border-radius: 15px;
  padding: 15px 40px;
  margin: 10px 0px;
  justify-content: center;
`;
const Title = styled.Text`
  font-size: 20px;
  font-weight: 600;
  color: #fff;
`;

const Button = props => {
  return (
    <ButtonContainer title = {props.title}>
      <Title>{props.title}</Title>
    </ButtonContainer>
  );
};

export default Button;

 

background-color: ${props => props.title === 'Mary' ? '#3498db' : '#9b59b6' };

를 보면 받아오는 프로퍼티의 값에 삼항연산자를 적용해놓았다. 이를 위해

<ButtonContainer title = {props.title}>

프로퍼티 값을 제공하고 있다.

 

결과를 보자.

 

 

 

 

3. attr

 

스타일드 컴포넌트는 뷰의 attr(속성)도 입력받아 변경할 수 있는데, attrs를 이용해서 변경할 수 있다.

예시를 보자.

 

- .../component/Input.js

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

const StyledInput = styled.TextInput`
    width: 200px;
    height: 60px;
    margin: 5px;
    padding: 10px;
    border-radius: 10px;
    border: 2px;
    border-color: #3498db;
    font-size: 24px;
`;

const Input = () => {
    return <StyledInput placeholder = "Enter text ... " placeholderTextColor = "#3498bd"/>;
};

export default Input;

 

- .../src/App.js

import React from "react";
import styled from "styled-components/native";
import Button from "../component/Button";
import Input from "../component/Input";


const Container = styled.View`
    flex: 1;
    background-color: #ffffff;
    align-items: center;
    justify-content: center;
`;

const App = () => {
    return (
        <Container>
            <Button title="Mary"/>
            <Button title="React Native"/>
            <Input />
        </Container>
    );
};

일단 다음처럼 텍스트를 입력 받는 창을 만들어보자.

 

이제 attrs을 이용해서 색상을 변경해보자.

 

- ../component/Input.js

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

const StyledInput = styled.TextInput.attrs(props => ({
    placeholder : 'Enter a text ...',
    placeholderTextColor : props.borderColor,
}))`
    ...
    border-color: ${props => props.borderColor};
    font-size: 24px;
`;

const Input = props => {
    return <StyledInput borderColor = {props.borderColor} />;
};

export default Input;

 

- ../src/App.js

import React from "react";
import styled from "styled-components/native";
import Button from "../component/Button";
import Input from "../component/Input";


const Container = styled.View`
    flex: 1;
    background-color: #ffffff;
    align-items: center;
    justify-content: center;
`;

const App = () => {
    return (
        <Container>
            <Button title="Mary"/>
            <Button title="React Native"/>
            <Input borderColor = "#3498db"/>
            <Input borderColor = "#9b59b6"/>
        </Container>
    );
};

보면 TextInput이 가지는 속성(attr)을 attrs로 변경하는 모습을 볼 수 있다.

 

 

4. ThemeProvider을 이용한 Theme

 

스타일 컴포넌트를 이용하면 안드로이드의 colors.xml, 혹은 theme.xml처럼 색을 저장해놓고 사용할 수 있다.

 

- ../component/theme.js

export const theme = {
    purple : '#9b55cc',
    blue : '#34bbdb',
};

 

- ../src/App.js

import React from "react";
import styled, { ThemeProvider } from "styled-components/native";
import Button from "../component/Button";
import Input from "../component/Input";
import { theme } from "../component/Theme";


const Container = styled.View`
    flex: 1;
    background-color: #ffffff;
    align-items: center;
    justify-content: center;
`;

const App = () => {
    return (
        <ThemeProvider theme = {theme}>
            <Container>
                <Button title="Mary"/>
                <Button title="React Native"/>
                <Input borderColor = "#3498db"/>
                <Input borderColor = "#9b59b6"/>
            </Container>
        </ThemeProvider>
    );
};

 

ThemeProvider을 통해 테마값을 적용하고 있다.

이 값을 통해 하위 컴포넌트들에 값을 적용할 수 있는데,

 

- .../component/Button.js

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

const ButtonContainer = styled.TouchableOpacity`
  background-color: ${props => props.title === 'Mary' ? props.theme.blue : props.theme.purple };
  border-radius: 15px;
  padding: 15px 40px;
  
 ...

 

props.theme를 통해 프로퍼티로 테마도 자연스럽게 넘어온걸 볼 수 있다.

 

 

테마 파일에서 선언한 색상으로 버튼이 변경된 것을 볼 수 있다.

 

이를 응용하면

 

- ../component/theme.js

...

export const lightTheme = {
    background: '#ffffff',
    text : '#ffffff',
    purple : '#9b55cc',
    blue : '#34bbdb',
}

export const darkTheme = {
    background: '#34495e',
    text : '#34495e',
    purple : '#9b55cc',
    blue : '#34bbdb',
}

 

- ../src/App.js

import React, { useState } from "react";
import styled, { ThemeProvider } from "styled-components/native";
import Button from "../component/Button";
import Input from "../component/Input";
import { darkTheme, lightTheme, theme } from "../component/Theme";
import { Switch } from "react-native";


const Container = styled.View`
    flex: 1;
    background-color: ${props => props.theme.background};
    align-items: center;
    justify-content: center;
`;

const App = () => {

    const [isDark, setIsDark] = useState(false);
    const toggleSwitch = () => setIsDark(!isDark)

    return (
        <ThemeProvider theme = {isDark ? darkTheme : lightTheme}>
            <Container>
                <Switch value= {isDark} onValueChange = {toggleSwitch} />
                <Button title="Mary"/>
                <Button title="React Native"/>
                <Input borderColor = "#3498db"/>
                <Input borderColor = "#9b59b6"/>
            </Container>
        </ThemeProvider>
    );
};

 

useState를 통해 초기값을 false로 두고, 버튼을 누를때마다 toggleSwitch함수를 통해 setIsDark 내부에 isDark값을 저장한다.

switch버튼을 통해 isDark 버튼의 값이 변경이 일어나면 isDark값을 가진 DOM을 다시 그리는데, 그 과정에서 ThemeProvider을 변경된다.

이를 통해 Container 내부에 선언되어있던 theme의 백그라운드 색이 변경되게 된다.

버튼도 변경할 수 있다.

 

- ../component/Button.js

...
const Title = styled.Text`
  font-size: 20px;
  font-weight: 600;
  color: ${props => props.theme.text};
`;
...

 

 

버튼을 통해 state가 변경되면서 뷰가 변경되는 것을 볼 수 있다.

반응형