일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 코딩테스트
- Color
- 구현
- Spring
- html
- Web
- SWEA
- DP
- 정렬
- front-end
- codecademy
- 해슁
- SQL
- 다이나믹 프로그래밍
- inflearn
- algorithm
- 자바
- Kotlin
- java
- 알고리즘
- CleanCode
- javascript
- 클린코드
- DFS
- 프로그래머스
- BFS
- CSS
- 검색트리
- 순환
- android
- Today
- Total
깡뇽
[ReactNative] 왕초보를 위한 React Native 101 (3) 본문
노마트코더에서 "왕초보를 위한 React Native 101"를 수강하며 공부한 부분들을 정리해보려고 한다.
#3.0 Introduction
새로운 프로젝트 만들기.
blank로 시작.
GitHub과 연동도 할 예정.
#3.1 Touchables
- 버튼만들기
justifyContent를 space-between으로 하면, Work와 Travel이 양 끝으로 배치된다.
다음으로 활성화상태에서의 버튼을 하얀색으로, 비활성화 상태에서 버튼은 회색이 되도록 하는 기능을 구현해야 한다.
colors.js 파일을 생성한 뒤에 색상 정보를 입력해두고, 이를 App.js의 코드에서 불러와 사용한다.
TouchableOpacity를 import한다. View처럼 사용하는데 press 이벤트를 감지하여 투명도가 조절되는 애니메이션이 적용된다.
속성을( activeOpacity={0} )로 설정하면 클릭했을 때, 사라져 보인다.
TouchableHighlight를 import한다. press 이벤트를 감지하여 배경을 조절할 수 있다.
속성을( underlayColor="#DDDDDD" )로 설정하여 클릭 시에 배경색을 정할 수 있다.
속성을( activeOpacity={0} )로 설정하면 클릭했을 때 글자가 사라져 보인다.
+) TouchableWithoutFeedback을 import한다. UI 변화는 없다.
+) Pressable을 사용하면 더욱 정밀한 이벤트들을 적용해볼 수 있었을 것이다. ex) delayLongPress으로 클릭 시간에 따른 설정을 할 수 있다. hitSlop 속성으로 클릭(이벤트 감지)의 범위를 설정할 수 있다.
#3.2 TextInput
- State 생성 및 활용
Work와 Travel의 활성화 상태를 구별하기 위한 State를 생성한다.
- textInput 적용
placeholder 속성을 추가할 수 있다.
Work를 클릭한 상태이면 Add a To Do가, Travel을 클릭한 상태이면 Where do you want to go?가 보인다.
- 스타일
- keyboardType 속성
keyboardType을 number-pad로 하면 숫자들만, email-address로 하면 @가 있는 키포드가 보여지고, phone-pad는 숫자패드에서 * # +가 더해진다.
- returnKeyType 속성
returnKeyType을 send로 하면 키보드에 send 버튼을 만들어 사용할 수 있다.
+) secureTextEntry로 비밀번호 입력시 입력 텍스트가 보이지 않도록 설정 가능. multiline으로 텍스트가 길어지면 길게 작성 가능. placeholderTextColor="red"로 placeholder의 색상을 변경할 수 있다.
- 텍스트 변화 확인
- State 활용
#3.3 To Dos
- alert 생성
- object로 입력형태 구조화하기
object assign으로 object를 가져다가 다른 object와 합친 뒤에 새로운 object를 return할 수 있도록 한다.
``` const newToDos = Object.assign({}, toDos, {[Date.now()]: {text, work:working},}); ```
해당 코드에서 첫 {}는 비어있으며 타겟 object가 된다.
toDos는 이전 object이다.
그 뒤에 {[Date.now()]: {text, work:working}}은 새로운 투두 object이다.
#3.4 Paint To Dos
- assign 코드 변경
object.assign 대신에 ES6방식을 사용할 수 있다.
``` const newToDos = {...toDos, [Date.now()]: {text, work:working},}; ```
- 스크롤 기능
ScrollView를 import한다.
toDos에 있는 key 값을 얻은 후에 toDos[key].text를 화면에 보여준다.
- 스타일 적용
스타일을 적절하게 변경하면 예쁘게 적용 가능하다.
#3.5 Persist
- Work와 Travel 정보 나누기
toDos의 true/false 정보와 working의 true/false 정보를 비교한다.
- 폰에 정보 저장
expo는 AsyncStorage가 있음. ``` expo install @react-native-async-storage/async-storage ``` 으로 설치. ( + npm install )
``` import AsyncStorage from '@react-native-async-storage/async-storage'; ```로 import도 해준다.
1) saveToDos 함수 : toSave 형태로 toDos를 받는데 addToDo 함수를 통해 saveToDos에 전달되는 것이다.
즉, addToDo 함수를 통해서 새로운 object를 생성하고, state에 넣어준다. 그리고 이어서 saveToDos 함수에도 새로운 object를 보낸다.
setItem의 첫 자리에는 key가 들어가고, 두번째 자리에는 value에 해당하는 string이 들어가야 하므로 stringify를 사용해서 object를 string으로 변환한다. 또한, Async와 await를 적용한다.
2) loadToDos 함수
저장시킨 값들을 다시 불로오기 위함이다.
string을 다시 object로 만들기 위해 JSON.parse()를 활용하다. 변환한 후에 setToDos 함수에 넣어서 업데이트한다.
#3.6 Dlete
- 삭제 버튼 생성 배치
- deleteToDo 함수 생성
새로운 object인 newToDos를 생성하고, 해당 object에서 key를 삭제한다.
그리고 setToDos 함수에 key가 삭제된 newToDos를 다시 넣는다.
추가로 alert 기능을 사용해서 삭제 버튼을 클릭했을 때에 삭제 여부를 다시 붇는 안내창을 띄울 수 있다.
#3.7 Recap
1) TouchableOpacity : 터치 이벤트가 발생하면 애니메이션 효과 발생. onPress, onPressIn, onPressOut, onLongPress 등의 옵션이 있다.
상단 해더의 Work와 Travel 버튼의 클릭에 따라 스타일 변화를 주고, true/false를 반환하여 TextInput 안에 힌트 메세지를 설정한다.
2) TextInput : 키보드 타입과 확인 버튼을 다양하게 설정할 수 있다.
3) 내용 작성, 저장, 삭제 함수 : 새로운 오브젝트를 만드는데 기존 내용에서 새로운 것을 합친다. 해당 object를 State에 저장하고, AsyncStorage에 저장하도록 한다. await를 적절히 사용해야 한다.
4) ScrollView : 내용들을 스크롤을 사용해서 조작할 수 있도록 한다. Object.keys(toDos)를 사용해서 오브젝트의 key를 활용할 수 있도록 한다.
import React, { useEffect, useState } from 'react';
import { StatusBar } from "expo-status-bar";
import {
Text,
View,
StyleSheet,
TouchableOpacity,
TextInput,
ScrollView,
Alert } from 'react-native';
import { Fontisto } from "@expo/vector-icons"
import AsyncStorage from '@react-native-async-storage/async-storage';
import { theme } from "./colors";
const STORAGE_KEY = "@toDos";
export default function App() {
const [working, setWorking] = useState(true);
const [text, setText] = useState("");
const [toDos, setToDos] = useState({});
useEffect(() => {
loadToDos();
}, []);
const travel = () => setWorking(false);
const work = () => setWorking(true);
const onChangeText = (payload) => setText(payload);
const saveToDos = async (toSave) => {
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(toSave));
};
const loadToDos = async () => {
const s = await AsyncStorage.getItem(STORAGE_KEY);
setToDos(JSON.parse(s));
};
const addToDo = async () => {
if(text === "") {
return;
}
// save to do
// const newToDos = Object.assign({}, toDos, {[Date.now()]: {text, work:working},});
const newToDos = {...toDos, [Date.now()]: {text, working},
};
setToDos(newToDos);
await saveToDos(newToDos);
setText("");
};
// console.log(toDos);
const deleteToDo = (key) => {
Alert.alert( "Delete To Do", "Are you sure?", [
{ text: "Cancel" },
{ text: "I'm Sure",
style: "destructive",
onPress: async () => {
const newToDos = {...toDos}
delete newToDos[key]
setToDos(newToDos);
saveToDos(newToDos);
} },
]);
};
return (
<View style={styles.container}>
<StatusBar style="auto"/>
<View style={styles.header}>
<TouchableOpacity onPress={work}>
<Text style={{...styles.btnText, color: working ? "white": theme.grey}}>Work</Text>
</TouchableOpacity>
<TouchableOpacity onPress={travel}>
<Text style={{...styles.btnText, color: !working ? "white": theme.grey}}>Travel</Text>
</TouchableOpacity>
</View>
<View>
<TextInput
onSubmitEditing={addToDo}
onChangeText={onChangeText}
returnKeyType="done"
value={text}
placeholder={working ? "Add a To Do": "Where do you want to go?"}
style={styles.input}/>
<ScrollView>{Object.keys(toDos).map((key) =>
toDos[key].working === working ? (
<View style={styles.toDo} key={key}>
<Text style={styles.toDoText}>{toDos[key].text}</Text>
<TouchableOpacity onPress={() => deleteToDo(key)}>
<Fontisto name="trash" size={18} color={theme.grey}/>
</TouchableOpacity>
</View>
) : null
)}
</ScrollView>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: theme.bg,
paddingHorizontal: 20,
},
header:{
justifyContent:"space-between",
flexDirection:"row",
marginTop: 100,
},
btnText:{
fontSize: 38,
fontWeight: "600",
},
input: {
backgroundColor: "white",
paddingVertical: 15,
paddingHorizontal: 20,
borderRadius: 20,
marginVertical: 20,
fontSize: 18
},
toDo:{
backgroundColor: theme.toDoBg,
marginBottom: 10,
paddingVertical: 20,
paddingHorizontal: 20,
borderRadius: 15,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
},
toDoText: {
color: "white",
fontSize: 16,
fontWeight: "500",
}
});
해당 코드에서 null 오류로 Android 실행이 되지 않았다.
loadToDos 함수에 is(s){}를 활용해 코드를 변경하였더니 이제 작동이 잘 되었다.
#3.8 Code Challenge
+) Work와 Travel 선택 저장, TODO내용 완료 확인, TODO내용 수정
++) publish가능.
btnText 스타일이 web에서 적용되지 않았는데 ``` ...styles.btnText ```이 적용되지 않아서 그런 것이므로 btnText 코드를 직접 넣어서 해결 가능.
아이콘 적용. assets에 있는 이미지들을 수정해서 적용 가능.
web 버전에서는 alert 기능 사용 불가능. platform을 확인할 수 있도록 Platform을 import 해줌.
빌드를 하기 위해서는 expo build:android 라고 터미널에 작성하면 됨.
'Web > ReactNative' 카테고리의 다른 글
[ReactNative] 왕초보를 위한 React Native 101 (2) (2) | 2022.05.16 |
---|---|
[ReactNative] 왕초보를 위한 React Native 101 (1) (0) | 2022.05.05 |