#오늘 배운 것
리액트 네이티브 delete,edit,api복습
native flex에 0.5도 적용이 된다,
uuid 는 리액트네이티브에 내장되어 있어 따로 설치가 필요없다.
모바일은 단위가 dp이다.
git clone을 하면 node_modules가 없다 > npm i 로 하면 전에 설치했던 패키지가 설치된다.
//리팩토링,firebase연동진행
import { StatusBar } from "expo-status-bar";
import {
Alert,
SafeAreaView,
ScrollView,
StyleSheet,
Text,
TextInput,
TouchableOpacity,
View,
} from "react-native";
import { useEffect, useState } from "react";
import AsyncStorage from "@react-native-async-storage/async-storage";
import Tabs from "./components/Tabs";
import Todo from "./components/Todo";
//install firebase --save : 디펜더씨를 위해 --save
import {
onSnapshot,
query,
collection,
doc,
orderBy,
addDoc,
getDoc,
getDocs,
updateDoc,
deleteDoc,
} from "firebase/firestore";
export default function App() {
// delete todo
// 삭제 이모티콘 터치 시 해당 todo 삭제
const [todos, setTodos] = useState([]);
const [category, setCategory] = useState(""); // js, react, ct
const [text, setText] = useState("");
const [editText, setEditText] = useState("");
const newTodo = {
// id: Date.now(),
text,
isDone: false,
isEdit: false,
category,
createdAt: Date.now(),
};
const addTodo = () => {
setTodos((prev) => [...prev, newTodo]);
setText("");
};
const deleteTodo = (id) => {
// 1. id 값을 받아서 해당 배열 요소를 제외한 나머지를 새로운 배열로 받는다.
// 2. setTodos
Alert.alert("Todo 삭제", "정말 삭제하시겠습니까?", [
{
text: "취소",
style: "cancel",
onPress: () => console.log("취소 클릭!"),
},
{
text: "삭제",
style: "destructive",
onPress: () => {
const newTodos = todos.filter((todo) => todo.id !== id);
setTodos(newTodos);
},
},
]);
};
const setEdit = (id) => {
const newTodos = [...todos];
const idx = newTodos.findIndex((todo) => todo.id === id);
newTodos[idx].isEdit = !newTodos[idx].isEdit;
setTodos(newTodos);
};
const editTodo = (id) => {
// 1. id 값받아서 해당 배열의 요소를 찾는다. idx 찾기
// 2. todos[idx].text = editText;
const newTodos = [...todos];
const idx = newTodos.findIndex((todo) => todo.id === id);
newTodos[idx].text = editText;
newTodos[idx].isEdit = false;
setTodos(newTodos);
};
const setDone = (id) => {
// 1. id를 매개변수로 받는다.
// 2. id에 해당하는 배열의 요소를 찾는다.
// 3. 그 배열의 요소의 isDone 값을 토글링한 후에 setTodos.
const newTodos = [...todos];
const idx = newTodos.findIndex((todo) => todo.id === id);
newTodos[idx].isDone = !newTodos[idx].isDone;
setTodos(newTodos);
};
const setCat = async (cat) => {
console.log("cat:", cat);
setCategory(cat);
//await AsyncStorage.setItem("category", cat);
// Update
await updateDoc(doc(dbService, "category", "currentCategory"), {
category: cat,
}); // doc 지정 후 변경할 속성 및 값 지정
};
useEffect(() => {
// 현재의 최신 todos를 AsyncStorage에 저장
const saveTodos = async () => {
await AsyncStorage.setItem("todos", JSON.stringify(todos));
};
if (todos.length > 0) saveTodos();
}, [todos]);
useEffect(() => {
// const getData = async () => {
// const resp_todos = await AsyncStorage.getItem("todos"); // todos 배열
// const resp_cat = await AsyncStorage.getItem("category"); // undefined / null
// setTodos(JSON.parse(resp_todos) ?? []);
// setCategory(resp_cat ?? "js");
// };
// getData();
// Read (내 Firestore collection 내에 변경이 생길 때 마다 실시간으로 읽기)
//1.onSnapshot API를 이용해 todos콜렉션에 변경이 생길 때 마다 2.todos 콜렉션 안의 모든 다큐먼드를 불러와 setTodos함.
const q = query(
collection(dbService, "todos"),
orderBy("createdAt", "desc") // 해당 collection 내의 docs들을 createdAt 속성을 내림차순 기준으로 정렬
);
const getCategory = async () => {
//firebase내부의 컬렉션과 문서ID,필드 초기값 작성 후
// Read (단일 데이터 읽기)
const snapshot = await getDoc(
doc(dbService, "category", "currentCategory")
); // 하나의 doc를 가져옴.
//console.log("snapshot", snapshot.id);
//console.log("snapshot.data()", snapshot.data());
setCategory(snapshot.data().category); // 가져온 doc의 객체 내용
//snapshot.id; // 가져온 doc의 id
getCategory();
};
}, []);
//firebase의 경우 store안에 todos와 category보관했다가 마운트 됐을때 불러와서(getData) setTodos,setCategory한다.
//AsyncStorage로 적용햇었던 todos와 category state를 보관했다가 마운트 했을 때 AsyncStorage를 불러와 setTodos,setCategory한다.
//setTodos(JSON.parse(resp_todos) ?? []);
//setCategory(resp_cat ?? "js");
return (
<SafeAreaView style={styles.safearea}>
<StatusBar style="auto" />
<View style={styles.container}>
<Tabs setCat={setCat} category={category} />
<View style={styles.inputWrapper}>
<TextInput
onSubmitEditing={addTodo}
onChangeText={setText}
value={text}
placeholder="Enter your task"
style={styles.input}
/>
</View>
<ScrollView>
{todos.map((todo) => {
if (category === todo.category) {
return (
<Todo
key={todo.id} //props이긴 하지만 컴포넌트에 내려지지 않는다...
editTodo={editTodo}
setDone={setDone}
deleteTodo={deleteTodo}
setEdit={setEdit}
todo={todo}
setEditText={setEditText}
editText={editText}
/>
);
}
})}
</ScrollView>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safearea: {
flex: 1,
},
container: {
flex: 1,
paddingVertical: 30,
paddingHorizontal: 20,
},
inputWrapper: {
borderTopWidth: 1,
borderBottomWidth: 1,
paddingVertical: 15,
marginTop: 15,
marginBottom: 15,
},
input: {
borderWidth: 1,
paddingVertical: 10,
paddingHorizontal: 20,
},
});
#후발대
'[내일배움캠프] > TIL' 카테고리의 다른 글
23.01.04) React native 심화를 배운 48일차 (0) | 2023.01.04 |
---|---|
23.01.03) React native 심화(navigate)를 배운 47일차 (0) | 2023.01.03 |
22.12.30) React native(add,edit,delete,api)를 배운 45일차 (0) | 2022.12.30 |
22.12.29) expo설치,React native(ui)를 배운 44일차 (0) | 2022.12.29 |
22.12.28) React팀프로젝트를 마무리한 43일차 (0) | 2022.12.29 |