[React-Native]To-Do-App 만들기(2)
in Study on react_native
이제 To Do App의 메인으로, 해야 할 일 부품을 만들어 주겠습니다.
ToDo 만들기
Todo.js를 생성하고 아래처럼 작성합니다.
// app/components/Todo.js
import React from "react"
import {View,Text,StyleSheet} from "react-native"
const TodoItem= () => (
<View style={styles.todoContainer}>
<View>
<Text style={styles.todos}>할일 1</Text>
</View>
</View>
)
const styles = StyleSheet.create({
todoContainer: {
padding: 5,
marginTop: 20,
borderBottomWidth:1
},
todos: {
fontSize: 20
},
})
export default TodoItem
View에 todoContainer라는 이름으로 style을 줍니다.
style 설정이 끝나면 App.js에 TodoItem을 import 한 뒤, 부품을 두 개 조립해봅니다.
//App.js
<View style={styles.container}>
<View style={styles.centered}>
<Header/>
</View>
<View style={styles.inputContainer}>
<SubTitle title="To-Do 입력"/>
<Input/>
</View>
<View style={styles.todoContainer}>
<SubTitle title="To-Do List"/>
<TodoItem/>
<TodoItem/>
</View>
</View>
실행 결과는 다음과 같습니다.
TodoItem의 width가 화면을 넘어가고 있으니 style을 조정해보겠습니다.
//Todo.js
import React from "react"
import {View,Text,StyleSheet,Dimensions} from "react-native"
const {width,height} = Dimensions.get('window')
const TodoItem= () => (
<View style={styles.todoContainer}>
<View>
<Text style={styles.todos}>할일 1</Text>
</View>
</View>
)
const styles = StyleSheet.create({
todoContainer: {
padding: 5,
marginTop: 20,
borderBottomWidth:1,
width: width-40
},
todos: {
fontSize: 20
},
})
export default TodoItem
Dimension을 이용하면 화면치수를 활용할 수 있습니다.
Dimensions.get('window')
는 화면의 width와 height를 객체 형태로 받아올 수 있는 코드입니다. 위처럼 값을 받아온뒤, 현재 화면 -40으로 todoContainer의 width를 설정해 줍니다.
Icon 추가하기
To-Do List에 한 일을 체크할 수 있는 버튼이 필요합니다.
먼저 버튼으로 사용할 아이콘을 추가해봅니다.
expo에서 기본으로 제공해주는 ‘FontAwesome’의 ‘check’ 아이콘을 사용하겠습니다.
//Todo.js
import React from "react"
import {View,Text,StyleSheet,Dimensions} from "react-native"
import {FontAwesome} from "@expo/vector-icons"
const {width,height} = Dimensions.get('window')
const TodoItem= () => (
<View style={styles.todoContainer}>
<View>
<FontAwesome name="check-circle" size={20}/>
<Text style={styles.todos}>할일 1</Text>
</View>
</View>
)
const styles = StyleSheet.create({
todoContainer: {
padding: 5,
marginTop: 20,
borderBottomWidth:1,
width: width-40
},
todos: {
fontSize: 20
},
})
export default TodoItem
FontAwesome의 check-circle을 가져와서 사용해 보겠습니다.
체크 ‘아이콘’이 생겨났습니다. 이제 이것을 ‘버튼’으로 만들어 보겠습니다.
TouchableOpacity
TouchableOpacity
는 사용자가 터치했을때 반짝이는 컴포넌트입니다.
TouchableOpacity
를 import 하고 사용하겠습니다.
//Todo.js
import {View,Text,StyleSheet,Dimensions,TouchableOpacity} from "react-native"
const TodoItem= () => (
<View style={styles.todoContainer}>
<View>
<TouchableOpacity>
<FontAwesome name="check-circle" size={20}/>
</TouchableOpacity>
<Text style={styles.todos}>할일 1</Text>
</View>
</View>
)
그리고 실행해보면, 클릭하거나 터치했을 때 반짝거리는 것을 볼 수 있습니다.
레이아웃 조정 및 삭제 버튼
레이아웃을 조정해 보고 삭제 버튼도 만들어 보겠습니다.
//Todo.js
const TodoItem= () => (
<View style={styles.todoContainer}>
<View>
<View style={styles.objContainer}>
<TouchableOpacity>
<FontAwesome name="check-circle" size={20}/>
</TouchableOpacity>
<Text style={styles.todos}>할일 1</Text>
<TouchableOpacity>
<FontAwesome name="close" size={20}/>
</TouchableOpacity>
</View>
</View>
</View>
)
const styles = StyleSheet.create({
todoContainer: {
padding: 5,
marginTop: 20,
borderBottomWidth:1,
width: width-40
},
todos: {
fontSize: 20
},
objContainer: {
flexDirection:'row'
}
})
React-Native의 컴포넌트들은 기본적으로 flexDirection
이 column
으로 설정되어 있습니다. 그렇기 때문에 모든 부품들이 세로로 쌓여있었습니다.
이렇게 세로로 배치된 컴포넌트들을 가로로 이어주려면 flexDirection
속성을 row
으로 변경해야합니다.
주의할 점은 flexDirection
속성이 변경되면, alignItems
가 세로정렬을, justifyContent
가 가로 정렬 방식을 조정하게 됩니다.
이제 레이아웃을 조정 했고 삭제 할 수 있는 버튼을 추가했습니다.
이제 레이아웃을 좀 더 조정해 보겠습니다.
//Todo.js
const TodoItem= () => (
<View style={styles.todoContainer}>
<View>
<View style={styles.objContainer}>
<View style={styles.textContainer}>
<TouchableOpacity>
<FontAwesome name="check-circle" size={20} style={styles.check}/>
</TouchableOpacity>
<Text style={styles.todos}>할일 1</Text>
</View>
<TouchableOpacity>
<FontAwesome name="close" size={20}/>
</TouchableOpacity>
</View>
</View>
</View>
)
const styles = StyleSheet.create({
todoContainer: {
padding: 5,
marginTop: 20,
borderBottomWidth:1,
width: width-40
},
todos: {
fontSize: 20
},
objContainer: {
flexDirection:'row',
justifyContent:'space-between'
},
textContainer: {
flexDirection:'row',
alignItems:'center'
},
check: {
marginRight: 10,
}
})
flexDirection
이 row
로 설정되어 있을 때, justifyContent
는 가로정렬 방식을 의미합니다. ``space-between`은 공백을 사이에 두고 정렬한다는 의미입니다.
현재 여기에선 objContainer안에 있는 View(textContainer)와 삭제 버튼을 정렬하되, 사이에 공백을 두고 정렬한다는 뜻입니다. 결과적으로 View는 왼편에 위치하게 되고, 삭제버튼은 오른편에 위치하게 됩니다.
그리고 textContainer
는 icon과 text를 세로로 중앙정렬 하기 위해 flexDirection
을 row
로 바꾸고 alignItems
를 이용하여 세로 정렬을 해주었습니다.
완료~!!
TodoItem 재사용하기 (Props)
할 일을 추가할 때마다 Todo.js를 새로 생성하는 것은 너무 비효율적입니다. 앞서 사용했던 Props를 이용해서 TodoItem을 재사용해보겠습니다.
//App.js
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={styles.centered}>
<Header/>
</View>
<View style={styles.inputContainer}>
<SubTitle title="To-Do 입력"/>
<Input/>
</View>
<View style={styles.todoContainer}>
<SubTitle title="To-Do List"/>
<TodoItem text="알바 가기" />
<TodoItem text="전화 하기"/>
</View>
</View>
)
}
}
//Todo.js
const TodoItem= ({text}) => (
<View style={styles.todoContainer}>
<View>
<View style={styles.objContainer}>
<View style={styles.textContainer}>
<TouchableOpacity>
<FontAwesome name="check-circle" size={20} style={styles.check}/>
</TouchableOpacity>
<Text style={styles.todos}>{text}</Text>
</View>
<TouchableOpacity>
<FontAwesome name="close" size={20}/>
</TouchableOpacity>
</View>
</View>
</View>
)
App.js 에서 TodoItem 부품을 조립하고, text
속성을 임의로 줍니다.
그리고 Todo.js에서 text를 받아와 출력해줍니다.