AsyncStorage
AsyncStorage
expo install @react-native-async-storage/async-storage
로그인 ⇒ 메인페이지 ⇒ 로그아웃 ⇒ Loading ⇒ 로그인 상태 체크 ⇒ 로그인이 되어 있으면 메인페이지로 ⇒ 로그인이 안 되어 있으면 로그인 페이지로
firebaseFunctions.js
import firebase from "firebase/compat";
import "firebase/compat/firestore";
import { Alert, AsyncStorage } from "react-native";
export async function registration(nickName, email, password, navigation) {
try {
await firebase.auth().createUserWithEmailAndPassword(email, password);
const currentUser = firebase.auth().currentUser;
const db = firebase.firestore();
db.collection("users").doc(currentUser.uid).set({
email: currentUser.email,
nickName: nickName,
});
await AsyncStorage.setItem("session", email);
navigation.push("TabNavigator");
} catch (err) {
Alert.alert("회원가입 실패 -> ", err.message);
}
}
export async function signIn(email, password, navigation) {
try {
await firebase.auth().signInWithEmailAndPassword(email, password);
await AsyncStorage.setItem("session", email);
navigation.push("TabNavigator");
} catch (err) {
Alert.alert("로그인 실패 -> ", err.message);
}
}
export async function logout(navigation) {
try {
const currentUser = firebase.auth().currentUser;
await AsyncStorage.removeItem("session");
await firebase.auth().signOut();
navigation.push("SignInPage");
} catch (err) {
Alert.alert("로그아웃 실패 -> ", err.message);
}
}
await AsyncStorage.setItem("session", email);
await AsyncStorage.removeItem("session");
SignInPage.jsx
useEffect(() => {
navigation.addListener("beforeRemove", (e) => {
e.preventDefault();
});
setTimeout(() => {
AsyncStorage.getItem("session", (err, result) => {
console.log("ASYNCSTORAGE");
console.log(result);
if (result) {
navigation.push("TabNavigator");
} else {
setReady(true);
}
});
setReady(true);
}, 1000);
}, []);
AddPage.jsx
const [title, setTitle] = useState("");
const [titleError, setTitleError] = useState("");
const [content, setContent] = useState("");
const [contentError, setContentError] = useState("");
const [image, setImage] = useState(tempImage);
const upload = () => {
console.log("upload");
};
AddPage.jsx
const upload = async () => {
const currentUser = firebase.auth().currentUser;
let date = new Date();
let data = {
title: title,
author: currentUser.email,
desc: content,
image: image,
date: date.getTime(),
uid: currentUser.uid,
};
let result = addDiary(data);
if (result) {
Alert("작성 완료");
}
};
firebaseFunctions.js
export async function addDiary(content) {
try {
const db = firebase.firestore();
await db
.collection("diary")
.doc(content.date + "D")
.set(content);
return true;
} catch (err) {
Alert.alert("글 작성 실패 -> ", err.message);
return false;
}
}
await db
.collection("diary")
.doc(content.date + "D")
.set(content);
diary
어떤 문서에 content.date + "D"
어떤 내용 content
expo-image-picker 설치
expo install expo-image-picker
AddPage.jsx
useEffect(() => {
getPermission();
}, []);
const getPermission = async () => {
if (Platform.OS !== "web") {
const { status } = await ImgaePicker.requestMediaLibraryPermissionsAsync();
if (status !== "granted") {
alert("사진 권한이 필요합니다.");
}
}
};
ImgaePicker.requestMediaLibraryPermissionsAsync()
함수로 사용자 권한 확인AddPage.jsx
const pickImage = async () => {
let imageData = await ImgaePicker.launchImageLibraryAsync({
mediaTypes: ImgaePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 4],
quality: 1,
});
};
launchImageLibraryAsync
부분을launchCameraAsync
로 바꾸면 카메라 실행
AddPage.jsx
const pickImage = async () => {
let imageData = await ImgaePicker.launchImageLibraryAsync({
mediaTypes: ImgaePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 4],
quality: 1,
});
getImageUrl(imageData);
};
const getImageUrl = async (imageData) => {
const response = await fetch(imageData.uri);
const blob = await response.blob();
};
Blob 객체는 파일류의 불변하는 미가공 데이터를 나타냅니다.
텍스트와 이진 데이터의 형태로 읽을 수 있으며,
ReadableStream으로 변환한 후 그 메서드를 사용해 데이터를 처리할 수도 있습니다.
Blob은 JavaScript 네이티브 형태가 아닌 데이터도 표현할 수 있습니다.
File 인터페이스는 사용자 시스템의 파일을 지원하기 위해
Blob 인터페이스를 확장한 것이므로, 모든 블롭 기능을 상속합니다.
fetch
는 주소가 전달되면 해당 주소를 실행시켜 결과값을 가져오는 함수
const [imageUri, setImageUri] = useState("");
const getImageUrl = async (imageData) => {
const response = await fetch(imageData.uri);
const blob = await response.blob();
setImageUri(imageData.uri);
};
...
// 원래 코드
// <Grid style={styles.imageUpload} onPress={() => pickImage()}>
// <Text style={styles.imageUploadPlus}>+</Text>
// </Grid>
{imageUri == '' ? (
<Grid style={styles.imageUpload} onPress={() => pickImage()}>
<Text style={styles.imageUploadPlus}>+</Text>
</Grid>
) : (
<Image
source={{ uri: imageUri }}
style={styles.imagePreview}
onPress={() => pickImage()}
/>
)}
firebaseFunctions.js
export async function imageUpload(blob, date) {
const storageRef = firebase
.storage()
.ref()
.child("diary/" + date);
const snapshot = await storageRef.put(blob);
const imageUrl = await snapshot.ref.getDownloadURL();
blob.close();
return imageUrl;
}
AddPage.jsx
const upload = async () => {
const currentUser = firebase.auth().currentUser;
let date = new Date();
let getTime = date.getTime();
let data = {
title: title,
author: currentUser.email,
desc: content,
image: image,
date: getTime,
uid: currentUser.uid,
};
const response = await fetch(imageUri);
const blob = await response.blob();
const imageUrl = await imageUpload(blob, getTime);
data.image = imageUrl;
};
const getImageUrl = async (imageData) => {
setImageUri(imageData.uri);
};
fetch
와 response.blob()
을 upload 함수로 옮김 -> 최종적으로 storage 함수에 blob 데이터와 이미지를 넘기는 형태AddPage.jsx
const upload = async () => {
const currentUser = firebase.auth().currentUser;
let date = new Date();
let getTime = date.getTime();
let data = {
title: title,
author: currentUser.email,
desc: content,
image: image,
date: getTime,
uid: currentUser.uid,
};
const response = await fetch(imageUri);
const blob = await response.blob();
const imageUrl = await imageUpload(blob, getTime);
data.image = imageUrl;
let result = await addDiary(data);
if (result) {
Alert.alert("등록 완료");
setTitle("");
setContent("");
setImage(tempImage);
setImageUri("");
}
};
<Item regular style={styles.title}>
<Input
placeholder="다이어리 제목을 입력해주세요!"
style={{ fontSize: 13 }}
value={title}
onChangeText={(text) => setTitle(text)}
/>
</Item>
<Form style={styles.contentLayout}>
<Textarea
rowSpan={5}
bordered
placeholder="내용을 입력해주세요"
style={styles.content}
value={content}
onChangeText={(text) => setContent(text)}
/>
</Form>
const [progress, setProgress] = useState(false);
const upload = async () => {
setProgress(true);
const currentUser = firebase.auth().currentUser;
let date = new Date();
let getTime = date.getTime();
let data = {
title: title,
author: currentUser.email,
desc: content,
image: image,
date: getTime,
uid: currentUser.uid,
};
const response = await fetch(imageUri);
const blob = await response.blob();
const imageUrl = await imageUpload(blob, getTime);
data.image = imageUrl;
let result = await addDiary(data);
if (result) {
Alert.alert("등록 완료");
setTitle("");
setContent("");
setImage(tempImage);
setImageUri("");
setProgress(false);
} else {
setProgress(false);
}
};
...
return (
<Container>
<HeaderComponent />
{progress == false ? null : (
<Image source={loading} style={styles.progress} />
)}
<Content>
...
progress: {
width: 100,
height: 100,
borderRadius: 100,
position: 'absolute',
top: '50%',
alignSelf: 'center',
zIndex: 2,
},
absolute
를 사용하여 주변 스타일 무시 (위치 직접 지정 필요)zIndex
속성을 통해 모든 컴포넌트 위에 자리
firebaseFunctions.js
export async function addDiary(content) {
try {
const db = firebase.firestore();
let userRef = await db.collection("users").doc(content.uid);
let data = await userRef.get().then((doc) => {
return doc.data();
});
content.author = data.nickName;
await db
.collection("diary")
.doc(content.date + "D")
.set(content);
return true;
} catch (err) {
Alert.alert("글 작성 실패 -> ", err.message);
return false;
}
}
const pickImage = async () => {
let imageData = await ImgaePicker.launchImageLibraryAsync({
mediaTypes: ImgaePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 4],
quality: 0,
});
getImageUrl(imageData);
};