웹개발/PRJ

[React] 도서리뷰사이트 prj - Firebase를 이용해 Create, Read 기능 구현하기

쌀쌀 2024. 2. 13. 12:19

이번 프로젝트에서 내가 담당한 기능은 firebase를 이용해 도서리뷰 데이터를 추가하고 읽어들이는 부분이다.

 

여러번 구현해봤던 로직이라 이번에도 어렵지 않게 구현할 수 있었다.

 

간단한 흐름만 정리하도록 하겠다. 

 

 

 1. Firebase를 세팅한다.

import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';

const firebaseConfig = {
  apiKey: process.env.REACT_APP_FB_API_KEY,
  authDomain: process.env.REACT_APP_FB_AUTH_DOMAIN,
  projectId: process.env.REACT_APP_FB_PROJECT_ID,
  storageBucket: process.env.REACT_APP_FB_STORAGE_BUCKET,
  messagingSenderId: process.env.REACT_APP_FB_MESSAGING_SENDER_ID,
  appId: process.env.REACT_APP_FB_APP_ID
};

const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);

 

 2. 데이터를 전역으로 관리하기 위해 redux를 세팅한다.

 

(1) configStore.js

import { createStore } from 'redux';
import { combineReducers } from 'redux';
import reviewsReducer from '../modules/reviewsReducer';
import authReducer from '../modules/authReducer';

const rootReducer = combineReducers({ reviewsReducer});
const store = createStore(rootReducer);

export default store;

 

(2) reviewsReducer.js

const SET_REVIEW = 'SET_REVIEW';
const ADD_REVIEW = 'ADD_REVIEW';

export const setReview = (data) => {
  return {
    type: SET_REVIEW,
    payload: data
  };
};

export const addReview = (data) => {
  return {
    type: ADD_REVIEW,
    payload: data
  };
};

const initialState = {
  reviews: []
};

const reviewsReducer = (state = initialState, action) => {
  switch (action.type) {
    case SET_REVIEW:
      return {
        ...state,
        reviews: action.payload
      };
    case ADD_REVIEW:
      return {
        ...state,
        reviews: [action.payload, ...state.reviews]
      };
    default:
      return state;
  }
};

export default reviewsReducer;

 

 

 3. useFirestore 훅을 만든다.

 

import { useEffect, useState } from 'react';
import { db } from '../firebase/firebase';
import { collection, getDocs, query, addDoc, orderBy } from 'firebase/firestore';
import { setReview } from '../redux/modules/reviewsReducer';
import { useDispatch } from 'react-redux';
const useFirestore = (collectionName) => {
  const [loading, setLoading] = useState(true);
  const dispatch = useDispatch();
  useEffect(() => {
    const fetchData = async () => {
      try {
        const q = query(collection(db, collectionName), orderBy('createdAt', 'desc'));
        const snapshot = await getDocs(q);
        const fetchedData = snapshot.docs.map((doc) => ({
          id: doc.id,
          ...doc.data() // 문서 데이터를 객체로 변환
        }));
        //초기값 세팅
        dispatch(setReview(fetchedData));
        setLoading(false);
        console.log('fetchedData', fetchedData);
      } catch (error) {
        console.error('Error fetching Firestore data:', error);
      }
    };

    fetchData(); // 데이터 가져오기 함수 호출

  }, [collectionName, dispatch]);

  const addData = async (newData) => {
    try {
      const collectionRef = collection(db, collectionName);
      const docRef = await addDoc(collectionRef, newData);
      console.log('Data added successfully!', docRef.id);
      return docRef.id;
    } catch (error) {
      console.error('Error adding data:', error);
    }
  };

  return { loading, addData };
};

export default useFirestore;

 

 4. 필요한 곳에서 호출한다.

 

fire store와 redux에 순차적으로 값을 add하는 로직을 호출한다.

const ReviewForm = ({ selectedBook, setIsModalOpen, setSelectedBook }) => {
  ...
  //호출함과 동시에 useFirestore에서 받아온 데이터를 state에 저장함
  const { addData } = useFirestore('book-reviews');

  ...
    const newReviewData = {
      title: title,
      content: content,
      image: selectedBook.image,
      bookAuthor: selectedBook.author,
      bookTitle: selectedBook.title,
      createdAt: new Date(),
      genre: selectedGenre,
      authorId: userInfo ? userInfo.uid : '',
    };
    //firestore에 저장을 하고
    const docId = await addData(newReviewData);
    newReviewData.id = docId;
    //dispatch로 state에도 저장한다.
    dispatch(addReview(newReviewData));
  };

  return (
    ...
  );
};

export default ReviewForm;

 

 

5. 작성하기 테스트

 

 

6. 리스트가 잘 저장되고 출력되는 걸 확인할 수 있다.