본문 바로가기
스파르타코딩클럽/내일배움캠프

[TIL] 내일배움캠프 React 과정 2023.01.11

by heereal 2023. 1. 13.

Today I Learend

  • React Native 팀 프로젝트 진행

 


Firebase Error: Need to provide options

import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth } from "firebase/auth";

// ❌이 위치에 넣으면 안됩니다.
const app = initializeApp(firebaseConfig);
export const dbService = getFirestore(app);
export const authService = getAuth(app);

const firebaseConfig = {
  apiKey: "AIzaSyD6trVgVLj_UzoKmBmZ2pWX44j9ZLgFGqk",
  authDomain: "nativetodolist.firebaseapp.com",
  projectId: "nativetodolist",
  storageBucket: "nativetodolist.appspot.com",
  messagingSenderId: "11037294657",
  appId: "1:11037294657:web:5072139462213feb8306c0",
  measurementId: "G-CRYTSRWK2D",
};

// ⭕firebaseConfig 하단에 넣으세요!!
const app = initializeApp(firebaseConfig);
export const dbService = getFirestore(app);
export const authService = getAuth(app);

Firebase: Need to provide options, when not being deployed to hosting via source. (app/no-options)

Undefined is not an object (evaluating ...firestore/dbService)

그냥 onSnapshot 이용해서 firestore에서 데이터 불러오는 간단한 문제였는데 자꾸 firebaseError가 발생했다. 에러 메시지로 검색해서 찾은 스택오버플로우 글에서 힌트를 찾았는데 firebaseConfig key를 넣기 전에 daService를 실행하다 보니 어디서 불러올지 option이 제공되지 않아서 문제가 됐던 거였다. 그래서 코드 세 줄을 firebaseConfig 하단으로 위치를 옮기니 에러가 사라졌다.

 

참고 https://stackoverflow.com/questions/74016589/how-can-i-provide-options-when-not-being-deployed-to-hosting-via-source

 

 

useMutation과 언마운트의 관계

const deleteComment = (id) => {
    // deleteDoc(doc(dbService, "communityComments", id));
    Alert.alert("댓글 삭제", "댓글을 정말 삭제하시겠습니다?", [
      {text: "취소",
      style: "cancel"},
      {text: "삭제",
      style: "destructive",
      onPress: () => {
        setIsOpenModal(false);
        deleteDoc(doc(dbService, "communityComments", id));
      }}
    ])
  };

 

Alert 컴포넌트가 언마운트되고 나서 deleteDoc을 실행하도록 구현하고 싶은데 어떻게 해야 할지 떠오르지 않는다. 일단 아쉽지만 댓글 삭제할 때 alert을 띄우지 않고 기능을 구현하기로 결정했다. 이 문제에만 계속해서 시간을 쏟을 수 없어서 프로젝트가 끝나면 다시 시도해 보기로 한다.

 

const deleteComment = async (id) => {
    const test =  Alert.alert("댓글 삭제", "댓글을 정말 삭제하시겠습니다?", [
      {text: "취소",
      style: "cancel",
      onPress: () => {
        setIsOpenModal(false);
      }
      },
      {text: "삭제",
      style: "destructive",
      onPress: () => {
        setIsOpenModal(false);
        return 'delete'
      }}
    ])

    if (test === 'delete') {
       deleteDoc(doc(dbService, "communityComments", id));
    }
  };

내가 시도했던 방법. delete를 return 했을 때만 deleteDoc을 실행하도록 하고 싶었지만 if문이 먼저 실행되며 test가 undefined가 떠서 실패했다.

 

참고 자료 https://stackoverflow.com/questions/48809762/how-to-await-for-the-response-of-alert-dialog-in-react-native

 

 

forEach와 map의 차이점

onSnapshot(q, (snapshot) => {  // q (쿼리)안에 담긴 collection 내의 변화가 생길 때 마다 매번 실행됨
	 snapshot.docs.map((doc) => {
          const newState = {
                id: doc.id,
                ...doc.data()
          }
    });
});

const newArr = [];
  querySnapshot.forEach((doc) => {
    const newObj = {
      id: doc.id,
      ...doc.data(),
    };
    newArr.push(newObj);
});

firestore에서 데이터를 불러오기 위해서 getDocs와 onShapshot 두 가지 방법이 존재하는데 (사실 다른 방법도 있음..) getDocs는 forEach를 쓰고 onSnapshot은 map을 써서 두 가지의 차이점이 뭘까 궁금해졌다.

 

  • map()은 새로운 배열을 반환한다.
  • forEach()는 주어진 함수를 배열 요소 각각에 대해 실행해서 기존의 araay를 변경할 뿐 리턴값을 출력하지는 않는다.

참고 https://dream-frontend.tistory.com/341

 

결과적으로 getDocs는 map이 newState라는 결괏값을 알아서 출력해 주고, onSnapshot은 forEach로 newObj를 만들어서 직접 newArr에 push를 해줘야 했던 거였다.

 

 

메인페이지에서 특정 게시물 클릭 시 params 넘기기

<PostBox 
  onPress={() => 
    navigate("Stack", {
      screen: "CommunityDetail",
      params: { getPostId: post.id}
    })
  }
>

게시물을 클릭했을 때 그 게시물의 id를 params로 넘긴다.

 

export default function CommunityDetail({ route: { params: { getPostId } }}) {
	...생략...
};

받을 때는 이렇게 받는다. getPostId를 이용해서 디테일 페이지에서 특정한 게시물의 데이터만 뜨도록 구현할 수 있다.

 

 

git add 문제 "already exists in index"

fatal: will not add file alias 'components/Common/MBTIModal.jsx' ('components/common/MBTIModal.jsx' already exists in index)

상단의 메시지가 뜨면서 git add 했을 때 MBTIModal.jsx가 스테이징 되지 않는 상황이 반복되었다. 문제의 원인은 해당 파일이 속하는 폴더를 Common에서 common으로 수정하면서 대소문자가 충돌(?)했던 것으로 보인다. 그래서 git add —force도 써 보고 common 폴더를 아예 삭제하고 새로 만든 global 폴더로 파일들을 옮기는 등의 방법으로 해결했다.

 

참고 https://m.blog.naver.com/qjawnswkd/222310459506

 

 

로그인/로그아웃이 즉시 반영되지 않는 문제

const handleAddBtn = () => {
    if (!user) {
      navigate("Stack", {
        screen: "Login",
      });
    } else {
      navigate("Stack", {
        screen: "CommunityAdd",
      });
    }
  };

 

 

만약에 로그아웃을 하고 바로 커뮤니티탭(메인페이지)으로 이동해서 글 작성 버튼을 누르면 회원이 아닐 시 글을 작성할 수 없게 유효성 검사를 했음에도 불구하고 로그인 페이지로 이동하지 않고 글을 작성할 수 있었다. 이것이 네이티브의 특성상 페이지를 이동할 때 매번 새로고침되는 것이 아니라 스크린이 차곡차곡 쌓이기(?) 때문이라고 생각해서 reset을 한 번 해주기로 했다. 

 

const logout = () => {
    signOut(authService)
      .then(() => {
        reset({
          index: 0,
          routes: [
            {
              name: "Tabs",
              params: {
                screen: "커뮤니티",
              },
            },
          ],
        });
      })
      .catch((err) => alert(err));
};

로그아웃 버튼을 클릭했을 때 reset을 적용했더니 로그인 여부가 실시간으로 반영되어 글이나 댓글을 작성할 때 유효성 검사를 더욱 정확하게 실시할 수 있었다.

 


회고

query를 사용하면서 댓글이 실시간으로 삭제되지 않아서 여러 방법을 탐구해 보다가 우선순위를 미뤄두고 더욱 급한 부분을 먼저 해결하기로 했다. 아마 리액트 네이티브의 특성으로 인해 발생한 문제인 거 같아서 빨리 리액트로 돌아가고 싶은 마음이 들기도 한다. ㅎㅎ

 

팀 프로젝트를 진행하며 매일매일 새로운 에러들을 마주치고 있는데 그것들을 모두 기록하지 않아서 아쉽기도 하다. 근데 그걸 전부 다 기록하려면 정말 끝이 없고 시간도 너무 오래 걸릴 거 같다. 그래서 일단은 큼직한 것들만 블로그에 남기고 있다.

 

 

댓글