React 뉴스피드 팀 프로젝트 3일차

규갓 God Gyu·2023년 11월 23일
0

프로젝트

목록 보기
23/81

11.23 팀 회의 내용

<메인페이지>

  1. 기존에는 카테고리 별 게시글 올리고 싶을땐, input 태그에 select로 선택했는데,
    카테고리 버튼을 클릭해서 해당 카테고리에 글을 남길 수 있게 변경
    전체보기 버튼을 눌렀을 땐 input 쪽에서 어느 카테고리에 글을 남길지 알려주는 select태그를 넣어주고,
    상세 카테고리 ex)발라드, 힙합 일땐 input쪽에서 select태그를 없애고 ex) To 발라드 같은 느낌으로
    사용자 입장에서 어느 카테고리에 글을 남길건지를 알려줘야 한다.
    window.confirm('000카테고리에 글을 등록하시겠습니까?');

※ 더 구현해야하는 기능

  • post 정렬해서 보여주기 (시간순) / 카테고리 별 post filtering / post없을 시 안내문구 띄우기
  • login 안되어 있을때 action 처리(게시물 등록 x) => 포커스가자마자 alert 경고문구 띄우기
  • 게시글 수정 및 삭제 시 작성자만 가능하도록 (작성자의 게시글만 수정 삭제 버튼 보이게)
  • header 우측 상단 login 안되어있을때, login하러 가는 창 구현
  • ?글 남길때 modal 띄우기(보류)

<게시물 CRUD>

※ 더 구현해야하는 기능

  • 모달창에서 수정 및 삭제 구현
  • 삭제기능 구현되었으나, 수정 만드는 과정에서 에러가 떠서 에러잡아야함
  • 리듀서함수로 빼기

<회원가입>

※ 더 구현해야하는 기능

  • 30% 정도 구현 (내일 오전까지 완성 가능)

<마이페이지>

※ 더 구현해야하는 기능

  • 홈으로 가기 버튼 헤더로 빼기
  • initialState 이미지 값 storage에서 가져오기
  • firebase에서 내가 쓴 글 리스트 가져오기(필터링해서 가져오기?)
  • 등록된 내가 쓴 글 없을 때 화면 렌더링
  • 등록된 프로필 사진 없을 때 화면 렌더링 (storage에 기본 사진 저장해서 불러오는 형식)
  • 닉네임값 가져오기
  • ?본인 게시글 수정 삭제
    [내일 기능 완료 후 해야할 일]
    발표 / css / 기능구현 영상편집 / etc

context 모듈화 작업

이번에 CRUD를 맡으며 개념이 확실하지 않으니 만드는데 항상 큰 틀만 생각했지 디테일한 부분을 어떻게 접근할지 막막해서 당장 눈앞에 있는 순서대로 막 만들다보니 엄청나게 혼종의 코드가 탄생하였다.

완성된 코드를 해석해보며 나름대로 내걸로 만들어보는 작업을 진행해보았다.

//전역관리 context
import {
  addDoc,
  collection,
  deleteDoc,
  doc,
  getDocs,
  updateDoc
} from 'firebase/firestore';
import { createContext, useEffect, useState } from 'react';
import { db } from '../firebase/firebase.config';

// 초기 값
const initialState = {
  //데이터 담아주는 배열
  posts: [],
  //이 함수들은 각각 해당되는 인자들을 받아와서 사용함
  createPost: ({ title, content, category, userInfo }) => {},
  updatePost: ({ postId, data }) => {},
  deletePost: ({ postId }) => {}
};

//context 생성
const PostContext = createContext(initialState);

//자식 컴포넌트에 값을 뿌려주기 위해 provider 사용
//context.Provider로 하위 컴포넌트들을 감싸줘야 데이터 제공 가능
//CRUD로직이나 상태 데이터들을 PostProvider에서 관리
const PostProvider = ({ children }) => {
  const [posts, setPosts] = useState([]);
  // 최초 1회 실행될때 firebase 데이터 가져오기
  useEffect(() => {
    // 메인 로직 함수로 넣어주기
    getPost();
  }, []);
  const getPost = () => {
    //getDocs하면 firebase 데이터문서 가져올 수 있음
    //db에서 posts라는 이름을 가진 collection을 가져옴
    //firestore은 데이터를 객체의 형태로 저장
    getDocs(collection(db, 'posts'))
      //데이터베이스 쿼리를 실행해서 객체로 반환
      .then((QuerySnapshot) => {
        //빈 배열에 담기 위해 생성
        const fetchedPosts = [];
        //querysnapshot은 반복가능한 객체
        QuerySnapshot.forEach((doc) => {
          //문서id와 문서data를 넣기
          fetchedPosts.push({ id: doc.id, ...doc.data() });
        });
        //그 값들을 posts안에 보관하기
        setPosts(fetchedPosts);
      })
      .catch((e) => {
        //에러로 then이 실행안되면 해당 문구 출력
        console.error('An Error occured while fetching posts');
        console.error(e);
      });
  };
  //post 만드는 함수 (여기서 선언하면 다른 컴포넌트에서 사용가능)
  const createPost = ({ title, content, category, userInfo }) => {
    const newPost = {
      //실제 사용하는 컴포넌트에서 title,content,category,userInfo값을 받아와야한다
      //역으로 자신컴포넌트에서 받은 값을 활용해서 create해준다는 의미
      title,
      content,
      createAt: new Date().toLocaleString(),
      category,
      userInfo
    };
    //firestore에도 저장한 데이터 넘겨주기
    //저장하고 다시 받아와야 ui에서도 바뀐 값 적용됨
    const collectionRef = collection(db, 'posts');
    //doc에 저장
    addDoc(collectionRef, newPost)
      .then((res) => {
        console.log('add success');
        //다시 저장한거 꺼내와서 리랜더링
        getPost();
      })
      //값 못 불러 왔을 경우 에러창나타내기
      .catch((e) => {
        console.error('An Error occurred while adding posts');
        console.error(e);
      });
  };
  //수정하고난 post를 나타내기 위한 전역 함수
  //해당 post를 가리키는 문서 id와 data값 변경을 위한 data가 필요함
  const updatePost = ({ postId, data }) => {
    //db의 posts 컬렉션 안에 문서 id인 postId를 postRef에 선언
    const postRef = doc(db, 'posts', postId);
    //해당 문서의 데이터를 update
    updateDoc(postRef, data)
      .then(() => {
        //변경된 데이터를 다시 가져옴
        getPost();
      })
      .catch((e) => {
        console.error('An Error occurred while updating posts');
        console.error(e);
      });
  };
  //삭제를 위한 함수, 해당 문서를 찾기위한 id가 필요
  const deletePost = ({ postId }) => {
    //posts컬렉션안의 문서 id를 참조하는 변수 postRef
    const postRef = doc(db, 'posts', postId);
    deleteDoc(postRef)
      .then(() => {
        //삭제하고 난 데이터를 불러옴
        getPost();
      })
      .catch((e) => {
        console.error('An Error occured while deleting posts');
        console.error(e);
      });
  };
  //실제 자식 컴포넌트에서 사용할 값들만 value로 묶어줌
  const value = { posts, createPost, updatePost, deletePost };

  //Provider를 통해 자식컴포넌트는 value 해당된 값을 사용할 수 있음
  //children은 자식컴포넌트로 정보를 전달하는 방법
  //즉 부모컴포넌트에서 자식컴포넌트를 어떤식으로 유동성있게 구성할건지를 정하는 layout이라고 생각하면 됨
  return <PostContext.Provider value={value}>{children}</PostContext.Provider>;
};

children을 인자와 return쪽에 넣어준 이유는
부모 컴포넌트에서 해당 PostContext.Provider로 감싼 자식태그인, PostProvider로 그 아래 자식태그들을 묶기 때문에 어떤식으로 배치되든 그 안에 컴포넌트에 얼마나 추가되든 유동적으로 값을 내려주기 위해 {children}을 사용하였다


profile
웹 개발자 되고 시포용

0개의 댓글