일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 스크롤이벤트
- supabase auth
- TS
- 안드로이드빌드에러
- map
- supabase authentication
- 타입스크립트
- meatadata
- generic
- Next.js
- 이진탐색
- set
- async
- 상속
- 배열중복요소제거
- 글또10기
- 글또10기x코드트리
- 페이지네이션
- xlsx-js-style
- reactnative
- 슬라이딩윈도우
- javascript
- interface
- app.post
- supabase 페이지네이션
- react
- extends
- array
- Spring
- Filter
- Today
- Total
rhanziy
React Native - AsyncStorage, Alert 본문
AsyncStorage
만들던 어플을 껐다 켜도 데이터가 저장이 되는 storage를 구성해보자!
react native에서 제공하는 AsyncStorage를 프로젝트에 설치해 사용하면 된다.
import도 잊지맙시다.
npx expo install @react-native-async-storage/async-storage
import AsyncStorage from '@react-native-async-storage/async-storage';
저장하기(set)
saveToDos -> AsyncStorage.setItem(데이터) 비동기 함수로 처리한다. JSON형식으로 저장해야함~
const addToDo = async() => {
if(text === '') { return }
const newToDos = {...toDos, [Date.now()] : {text, work:working}}
setToDos(newToDos);
await saveToDos(newToDos);
setText("");
}
const saveToDos = async(toSave) => {
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(toSave))
}
가져오기(get)
JSON데이터를 parse해서 getItem으로 꺼낸다.
const loadToDos = async() => {
const s = await AsyncStorage.getItem(STORAGE_KEY);
s !== null ? setToDos(JSON.parse(s)) : null;
}
loadToDos 함수는 useEffect 훅을 사용해 접속시에 실행되는데, 그때 스토리지에 데이터가 저장되어있지 않으면
Cannot convert null value to object
에러가 발생한다. 그러니 데이터가 있는지 없는 지 조건을 검사하고 뿌려줄 데이터를 set한다.
그리고 get, set 모두 try catch문을 사용하는게 안전함,,,
https://react-native-async-storage.github.io/async-storage/docs/usage/
Usage | Async Storage
Async Storage can only store string data. In order to store object data,
react-native-async-storage.github.io
Alert
delete 기능을 추가해보자~ 일단 delete 버튼 ui를 만들어주고, onPress하면 deletToDo에 key값이 파라미터로 넘겨져 실행된다. 여기서 key값은 toDos object의 key만 뽑아다가 map 돌린 것.
<ScrollView>
{
Object.keys(toDos).map(key =>
toDos[key].work === working ?
(
<View key={key} style={styles.toDo}>
<Text style={styles.toDoText}>{toDos[key].text}</Text>
<TouchableOpacity onPress={()=>{deleteToDo(key)}} activeOpacity={0.5}>
<Fontisto name="trash" size={15} color={theme.grey} />
</TouchableOpacity>
</View>
)
: null
)}
</ScrollView>
Alert api를 사용해서 confirm 창을 구현했다.
Alert api는 객체 배열 타입의 alertButton도 제공하는데, text 속성으로 버튼라벨을 달고 onPress 속성으로 버튼 클릭시 콜백함수를 작성한다. iOS에서는 style : 'destructive' 로 버튼 스타일도 줄 수 있음.
const deleteToDo = async(key) => {
Alert.alert(
"Delete To Do?",
"Are you sure?", [
{ text : "Cancel" },
{
text : "I'm Sure",
onPress : () => {
const newToDos = {...toDos};
delete newToDos[key];
setToDos(newToDos);
saveToDos(newToDos);
}
},
// iOS에서만 적용
style : 'destructive'
])
}
🔽 전체코드
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View, TouchableOpacity, TextInput, ScrollView, Alert } from 'react-native';
import { theme } from './colors';
import { useEffect, useState } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Fontisto } from '@expo/vector-icons';
const STORAGE_KEY = "@toDos"
export default function App() {
const [working, setWorking] = useState(true);
const [text, setText] = useState("");
const [toDos, setToDos] = useState({});
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);
s !== null ? setToDos(JSON.parse(s)) : null;
}
useEffect(() => {
loadToDos();
}, []);
const addToDo = async() => {
if(text === '') { return }
const newToDos = {...toDos, [Date.now()] : {text, work:working}}
setToDos(newToDos);
await saveToDos(newToDos);
setText("");
}
const deleteToDo = async(key) => {
Alert.alert(
"Delete To Do?",
"Are you sure?", [
{ text : "Cancel" },
{
text : "I'm Sure",
onPress : () => {
const newToDos = {...toDos};
delete newToDos[key];
setToDos(newToDos);
saveToDos(newToDos);
},
style : 'destructive'
},
])
}
return (
<View style={styles.container}>
<StatusBar style="auto" />
<View style={styles.header}>
<TouchableOpacity activeOpacity={0.5} onPress={work}>
<Text style={{...styles.btnText, color: working ? "white" : theme.gray}}>Work</Text>
</TouchableOpacity>
<TouchableOpacity activeOpacity={0.5} onPress={travel}>
<Text style={{...styles.btnText, color : !working ? "white" : theme.gray}}>Travel</Text>
</TouchableOpacity>
</View>
<View>
<TextInput
onSubmitEditing={addToDo}
placeholder={working ? "Add a To Do" : "Where do you want to go?"}
value={text}
style={styles.input}
keyboardType='email-address'
returnKeyType='done'
onChangeText={onChangeText}
/>
</View>
<ScrollView>
{
Object.keys(toDos).map(key =>
toDos[key].work === working ?
(
<View key={key} style={styles.toDo}>
<Text style={styles.toDoText}>{toDos[key].text}</Text>
<TouchableOpacity onPress={()=>{deleteToDo(key)}} activeOpacity={0.5}>
<Fontisto name="trash" size={15} color={theme.grey} />
</TouchableOpacity>
</View>
)
: null
)}
</ScrollView>
</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: "500",
},
input : {
backgroundColor: "white",
paddingVertical: 15,
paddingHorizontal: 20,
borderRadius: 30,
marginVertical: 20,
fontSize : 18
},
toDo: {
flexDirection: "row",
justifyContent : "space-between",
alignItems : "center",
marginBottom : 10,
paddingVertical : 20,
paddingHorizontal : 20,
backgroundColor : theme.toDoBg,
borderRadius: 15,
},
toDoText : {
color:"white",
fontSize : 16,
fontWeight: "500"
}
});
https://reactnative.dev/docs/next/alert#alertbutton
Alert · React Native
Launches an alert dialog with the specified title and message.
reactnative.dev
'React Native' 카테고리의 다른 글
React Native - 에러해결 invalid hook call error(feat.카카오로그인) (1) | 2023.11.03 |
---|---|
React Native - edit기능 구현 중 too many re-renders(에러) (2) | 2023.10.10 |
React Native - TextInput component (0) | 2023.10.10 |
React Native - Touchable/Pressable component (0) | 2023.10.10 |
React Native - expo icon 사용하기 (0) | 2023.10.06 |