이 글은 <처음 배우는 리액트 네이티브(김범준, 한빛미디어)>를 읽고 이해한 바를 바탕으로 작성되었습니다.
https://github.com/Alchemist85K/my-first-react-native
리액트 네이티브에서 컴포넌트에 스타일을 적용하는 방법은 css와 유사한 부분이 많았다.
하지만,, 유사한 거지 똑같은 건 아니다.
css에서는 하이픈(-)을 사용하지만 react native에서는 카멜 표기법으로 작성한다. 일부 값들은 css 속성과 이름이 같지만 타입이 다른 경우, 단위가 생략되는 경우도 있다. 이건, 비슷해서 더 헷갈린다!!
이런 불편함을 해소하기위해 사용할 수 있는 것이 스타일드 컴포넌트(styled-components)이다.
스타일드 컴포넌트는 자바스크립트 파일 안에 스타일을 작성하는 CSS-in-JS 라이브러리이며, 스타일이 적용된 컴포넌트이다.
💡스타일드 컴포넌트 사용하기
스타일 컴포넌트를 사용하기 위해서는 각 프로젝트 파일안에서 아래 명령어를 이용하여 스타일드 컴포넌트를 설치해야한다.
중요한건, 스타일드 컴포넌트를 사용하려면 프로젝트 각각 매번 설치해주어야한다!!!
npm install styled-components
((
사실 나는 이 스타일드 컴포넌트를 import하는데서부터 계속 오류가 났었다. 약 3주 동안 해결을 못했었다.
이 styled-components를 설치하는 경로 문제 + expo SDK 버전 문제때문에 계속 오류가 났었다.
+ 에러 해결 방법
https://eunbin00.tistory.com/32
))
이렇게 설치를 해주면 스타일드 컴포넌트를 사용할 수 있다.
예시코드는 다음과 같다.
import styled from 'styled-components/native'
const MyTextStyledComponent = styled.Text`
color: #fff;
`;
이렇게 styled.[컴포넌트 이름] 뒤에 백틱(`)을 사용하여 만든 문자열을 붙이고, 그 안에 스타일을 css로 작성해주면된다.
이런 문법을 tagged template literal이라 한다고 한다.
💡스타일드 컴포넌트를 사용하는 이유
앱을 만든다고 생각해보자.
분명, 공통적인 스타일을 적용해야 하는 경우가 생길거고, 이 코드를 매번 작성하는 건 너무 비효율적인 일이다.
중복되는 스타일을 재하용 가능한 코드로 분리해내는 상황에서 스타일드 컴포넌트에서는 css를 이용하여 재사용이 가능한 코드를 관리할 수 있다.
import styled, {css} from 'styled-components/native';
const whiteText = css`
color: #fff;
font-size: 14px;
`;
const MyBoldTextComponent = styled.Text`
${whiteText}
font-weight: 600
`;
const MyLightTextComponent = styled.Text`
${whiteText}
font-weight: 200
`;
whiteText를 css를 이용해 스타일을 지정해놓고 다른 comonent에서 ${whiteText}로 재사용할 수 있다.
또, 완성된 컴포넌트를 상속받아 이용하는 방법도 있다.
import styled from 'styled-components/native';
const StyledText = styled.Text`
color: #000;
font-size: 20px;
margin: 10px;
padding: 10px;
`;
const ErrorText = styled(StyledText)`
font-weight: 600;
color: red;
`;
이렇게 스타일드 컴포넌트로 이미 만들어 놓은 컴포넌트를 styled(상속받을 컴포넌트 이름)``;로 소괄호로 감싸주면 상속받아올 수 있다.
💡스타일드 컴포넌트로 스타일 적용하기
직접 스타일드 컴포넌트로 버튼 컴포넌트를 만들어보겠다.
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-weight: 600;
color: #fff;
`;
const Button = props => {
return (
<ButtonContainer>
<Title>{props.title}</Title>
</ButtonContainer>
);
};
export default Button;
/* src/components/Button.js */
TouchableOpacity 컴포넌트와 Text 컴포넌트에 스타일드를 적용해서 ButtonContainer와 Title 컴포넌트를 만들었고, Button 컴포넌트에 넣어주었다.
import React from 'react';
import styled from 'styled-components/native';
import Button from './components/Button';
const Container = styled.View`
flex: 1;
background-color: #ffffff;
align-items: center;
justify-content: center;
`;
const App = () => {
return (
<Container>
<Button title='Eunbin' />
<Button title='React Native' />
</Container>
);
};
export default App;
/* src/App.js */
view 컴포넌트에 스타일드를 적용하여 Container 컴포넌트를 만들었고, App에 Container안에 Button 컴포넌트 2개를 props와 함께 넣어준다.
💡props 사용하기
스타일드 컴포넌트에서는 스타일을 작성하는 백틱(`)안에서 props에 접근할 수 있다는 장점을 이용해서 스나일을 작성하는 곳에서 조건에 따라 스타일을 변경할 수 있다.
예를 들어, 버튼 컴포넌트에서 props로 전달되는 title값이 'Eunbin'인 경우, 배경색을 바꿔준다고 하면,
import React from 'react';
import styled from 'styled-components/native';
const ButtonContainer = styled.TouchableOpacity`
background-color: ${props =>
props.title === 'Eunbin' ? '#3498db' : '#9b59b6'};
border-radius: 15px;
padding: 15px 40px;
margin: 10px 0px;
justify-content: center;
`;
const Title = styled.Text`
font-weight: 600;
color: #fff;
`;
const Button = props => {
return (
<ButtonContainer title={props.title}>
<Title>{props.title}</Title>
</ButtonContainer>
);
};
export default Button;
/* src/comonents/Button.js */
이렇게 스타일 작성에서 직접 props에 접근하여 조건 지정이 가능하다!
💡attrs 사용하기
# 스타일드 컴포넌트를 사용하면 스타일을 지정하는 곳에서 컴포넌트의 속성을 지정하는 것도 가능하다.
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 a text...' placeholderTextColor='#3498db' />
}
export default Input;
import React from 'react';
import styled from 'styled-components/native';
import Button from './components/Button';
import Input from './components/Input';
const Container = styled.View`
flex: 1;
background-color: #ffffff;
align-items: center;
justify-content: center;
`;
const App = () => {
return (
<Container>
<Button title='Eunbin' />
<Button title='React Native' />
<Input />
</Container>
);
};
export default App;
스타일드로 만든 StyledIput 컴포넌트에 placeholder 속성과 placeholderTextColor 속성을 지정해주었다.
# 속성을 설정할 때, 앞에서 본 것처럼 전달된 props에 접근할 수 있기 때문에 props의 값에 따라서 속성을 변경할 수도 있다.
import React from 'react';
import styled from 'styled-components/native';
const StyledInput = styled.TextInput.attrs(props => ({
placeholder: 'Enter a text...',
placeholderTextColor: props.borderColor,
}))`
width: 200px;
height: 60px;
margin: 5px;
padding: 10px
border-radius: 10px;
border: 2px;
border-color: ${props => props.borderColor};
font-size: 24px;
`;
const Input = props => {
return <StyledInput borderColor={props.borderColor} />;
}
export default Input;
/* src/components/Input.js */
스타일 속성 지정에서 border-color를 props로 받아온 값으로 설정하도록 하고,
import React from 'react';
import styled from 'styled-components/native';
import Button from './components/Button';
import Input from './components/Input';
const Container = styled.View`
flex: 1;
background-color: #ffffff;
align-items: center;
justify-content: center;
`;
const App = () => {
return (
<Container>
<Button title='Eunbin' />
<Button title='React Native' />
<Input borderColor='#3498db'/>
<Input borderColor='#9859b6' />
</Container>
);
};
export default App;
/* App.js */
Input 컴포넌트에서 prop로 borderColor에 값을 지정하여 넘겨준다!
이렇게 attrs를 이용하면 스타일을 설정하는 곳에서 props의 값에 따라 컴포넌트의 속성을 다르게 적용할 수도 있고, 항상 일정하게 적용할 수도 있다.
💡ThemeProvider
스타일드 컴포넌트의 ThemeProvider는 Context API를 활용해 애플리케이션 전체에서 스타일드 컴포넌트를 이용할 때 미리 정의한 값들을 사용할 수 있도록 props로 전달한다.
#미리 정의한 색 사용하기
export const theme = {
purple: '#9b59b6',
blue: '#3498db',
};
/* src/theme.js */
theme.js 파일을 따로 만들어서, 사용할 색을 puple, blue로 미리정의해둔다.
import React from 'react';
import styled from 'styled-components/native';
const ButtonContainer = styled.TouchableOpacity`
background-color: ${props =>
props.title === 'Eunbin' ? props.theme.blue : props.theme.purple};
border-radius: 15px;
padding: 15px 40px;
margin: 10px 0px;
justify-content: center;
`;
const Title = styled.Text`
font-weight: 600;
color: #fff;
`;
const Button = props => {
return (
<ButtonContainer title={props.title}>
<Title>{props.title}</Title>
</ButtonContainer>
);
};
export default Button;
/* src/compoenents/Button.js */
Button 컴포넌트에서 스타일을 정의할 때, props로 전달되는 theme을 이용하도록 하였다.
import React from 'react';
import styled, {ThemeProvider} from 'styled-components/native';
import Button from './components/Button';
import Input from './components/Input';
import {theme} from './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='Eunbin' />
<Button title='React Native' />
<Input borderColor='#3498db'/>
<Input borderColor='#9b59b6' />
</Container>
</ThemeProvider>
);
};
export default App;
/* App.js */
themeprovider와 만들어둔 theme.js를 불러와서 App Component 안에서 Themeprovider로 묶어준다.
((저기 input 컴포넌트에서도 theme.blue, theme.purple을 사용해보고 싶은데, 어떻게 사용해야하는지 모르겠다...,,,ㅜ_ㅜ))
이렇게 ThemeProvider를 사용해서 theme을 지정하면 하위 컴포넌트에서 theme의 미리 정의된 색을 모두 사용할 수 있다. 변수명도 의미있게 사용할 수 있고, 색의 관리와 사용 유지보수도 훨씬 효율적일 수 있다.
+) Theme을 두 개의 색을 정의해두고 사용자에 선택에 따라 Theme을 제공할 수도 있다. 우리가 쉽게 접할 수 있는 light Theme과 dart Theme을 사용하는 방식이 이런 식이다!
export const lightTheme = {
background: '#ffffff',
text: '#ffffff',
purple: '#9b59b6',
blue: '#3498db',
};
export const darkThme = {
background: '#34495e',
text: '#34495e',
purple: '#9b59b6',
blue: '#3498db',
};
/* src/theme.js */
우선, theme.js 파일에 lightTheme과 darkTheme에서 사용할 색을 정의한다.
import React, {useState} from 'react';
import {Switch} from 'react-native';
import styled, {ThemeProvider} from 'styled-components/native';
import Button from './components/Button';
import Input from './components/Input';
import {lightTheme, darkTheme} from './theme'
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='Eunbin' />
<Button title='React Native' />
<Input borderColor='#3498db' />
<Input borderColor='#9b59b6' />
</Container>
</ThemeProvider>
);
};
export default App;
/* App.js */
useState로 테마의 상태를 관리할 isDark와 상태를 변경할 setIsDark 함수를 만들고
Switch 컴포넌트를 활용해서 isDark의 상태를 변경할 수 있게 하였다.
import React from 'react';
import styled from 'styled-components/native';
const ButtonContainer = styled.TouchableOpacity`
background-color: ${props =>
props.title === 'Eunbin' ? props.theme.blue : props.theme.purple};
border-radius: 15px;
padding: 15px 40px;
margin: 10px 0px;
justify-content: center;
`;
const Title = styled.Text`
font-weight: 600;
color: #fff;
color: ${props => props.theme.text};
`;
const Button = props => {
return (
<ButtonContainer title={props.title}>
<Title>{props.title}</Title>
</ButtonContainer>
);
};
export default Button;
/* src/component/Button.js */
버튼의 title 색깔도 theme의 text props로 받아오도록 만든다.
'JavaScript > React-Native' 카테고리의 다른 글
[react-native] Hooks(1) useState (0) | 2021.08.21 |
---|---|
[react-native] styled-component를 import하는데 오류가 난다면? (0) | 2021.08.21 |
[react native] Props 완벽 정리 (0) | 2021.08.08 |
[react native] 컴포넌트 만들기 (0) | 2021.08.08 |
[react native] JSX 기본 문법 압축 정리 (0) | 2021.08.08 |
댓글