본문 바로가기

[내일배움캠프]/TIL

23.01.02) React native 복습 및 배운 46일차

#오늘 배운 것

 

리액트 네이티브 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,
  },
});

 

#후발대