2020/02/16
최종 모습
import React from 'react';
import styled from 'styled-components/native';
interface Props {
iconName: 'plus' | 'minus';
onPress?: () => void;
}
const Button = ({ iconName, onPress }: Props) => {
return (
<Container onPress={onPress}>
<Icon
source={
iconName === 'plus'
? require('~/assets/images/plus.png')
: require('~/assets/images/minus.png')
}
/>
</Container>
);
};
export default Button;
const Container = styled.TouchableOpacity``;
const Icon = styled.Image``;
interface Props{}
를 사용하여 Props의 타입을 정해준다.interface Props {
iconName: 'plus' | 'minus';
// iconName은 plus와 minus라는 string만 받는다. " : "는 필수항목을 나타낸다.
onPress?: () => void;
// onPress는 반환값이 없는 함수로 설정. " ?: " 는 필수항목은 아님을 나타낸다.
// iconName은 설정하지 않으면 error가 발생하고,
// onPress는 설정하지 않더라도 error가 나지 않는다.
}
const Button = ({iconName, onPress}: Props) => {
TouchableOpacity
컴포넌트를 이용하였다.activeOpacity
가 있다. default값은 0.2이고, 0~1까지 값을 지정해 줄 수 있다.<Container activeOpacity={0.5} onPress={onPress}>
...
</Container>
<Icon
source={
iconName === 'plus'
? require('~/assets/images/plus.png')
: require('~/assets/images/minus.png')
}
Image
컴포넌트를 이용하였다.source
에 경로를 지정하게 되고 require
구문을 사용하게 된다.src/assets/images
폴더안에 들어가게된다.add.png / add@2x.png / add@3x.png
로 이름을 변경하여 넣어준다. react-native는 해당 단말기의 화면 사이즈에 맞는 image를 불러와 랜더링 하게 된다.import React, { useState } from 'react';
import styled from 'styled-components/native';
import Button from '~/components/Button';
interface Props {
title?: string;
initValue: number;
}
const Counter = ({ title, initValue }: Props) => {
const [count, setCount] = useState < number > 0;
return (
<Container>
{title && (
<TitleContainer>
<TitleLabel>{title}</TitleLabel>
</TitleContainer>
)}
<CounterContainer>
<CounterLabel>{initValue + count}</CounterLabel>
</CounterContainer>
<ButtonContainer>
<Button iconName="plus" onPress={() => setCount(count + 1)} />
// 필수항목인 iconName은 꼭 설정하여준다.
<Button iconName="minus" onPress={() => setCount(count - 1)} />
</ButtonContainer>
</Container>
);
};
export default Counter;
const Container = styled.View`
flex: 1;
`;
const TitleContainer = styled.View`
flex: 1;
justify-content: center;
align-items: center;
/* padding-top: 30px; */
`;
const TitleLabel = styled.Text`
font-size: 44px;
color: #fff;
font-weight: bold;
`;
const CounterContainer = styled.View`
flex: 2;
justify-content: center;
align-items: center;
`;
const CounterLabel = styled.Text`
font-size: 100px;
font-weight: bold;
color: #fff;
`;
const ButtonContainer = styled.View`
flex: 1;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-around;
`;
interface Props {
title?: string;
// 필수항목이 아닌 title, type은 string
initValue: number;
// 필수항목인 initValue, type은 number
}
const Counter = ({title, initValue}: Props) => {
const[ 변수명, 변수를 변경할 set함수 ] = useState<state의 type>(초기값);
const Counter = ({title, initValue}: Props) => {
const [count, setCount] = useState<number>(0);
render(
...
)
}
interface Props{...}
interface State{
name: string;
age: number;
}
...
const [ user, setUser ] = useState<state>({
name: "홍길동",
age: 20
})
import React from 'react';
import styled from 'styled-components/native';
import Counter from './screens/counter';
interface Props {}
const App = ({ }: Props) => {
// props가 없지만 type은 설정해 준다.
return (
<Body>
<Counter title={'This is Counter App'} initValue={1004} />
// 필수 항목인 initValue를 작성해 준다.
</Body>
);
};
export default App;
const Body = styled.View`
background-color: #000;
opacity: 0.85;
flex: 1;
`;
display: flex;
라고 값을 주지만, native에서는 flex: 1;
이라고 작성flex: 1;
의 의미가 화면 전체를 사용하겠다는 의미로 받아드렸습니다. flex: 1이 선언된 컴포넌트의 자식이 둘이라면 flex: 1;
을 선언한 컴포넌트와 flex: 2;
를 선언한 컴포넌트가 있다면 1:2의 비율
로 화면을 나눠가지게 됩니다.flex-direction: row;
를 작성해야합니다.