2021~_Projects/JStargram

4일차 CSS/기능 리팩토링 및 배포 완료

Indie Olineoguli 2021. 4. 9. 23:56

작업 내용

  • Complete chatroom function 
    • Add chat-room in each picture
    • Chat function is available for logined user
    • Applied CSS and CSS-Animation
    • Applied Media-Query(Responsive Web for Laptop/Tablet/Mobile)
  • Apply dotenv for firebase API Key
    • Hide all of sensitive info in .env
  • Deploy app by Firebase

배포주소: https://j-star-gram.firebaseapp.com/

 

chatroom.js

1) get data and render

데이터베이스에 변화가 있을때마다 새 데이터(모든 메세지데이터)를 불러오는데,

imgId === selectedImgId 즉, 선택된 사진에 관련된 메세지 데이터만 가져올 수 있도록 filter 메소드를 이용하여 필터링한다.

이를 위해서 imgId 라는 객체를 메세지 데이터에 포함시켰다. 박스안의 스트링이 자동으로 생성되는 이미지 id 이다.

import React, { useState, useEffect } from "react";
import { timeStamp } from "../firebase/config";
import styled from "styled-components";
import { motion } from "framer-motion";
import Message from "./message";
import firebase from "firebase/app";

const Chatroom = ({ user = null, selectedImgId = null }) => {
  const [messages, setMessages] = useState([]);
  const [newMessage, setNewMessage] = useState("");
  const { uid, displayName, photoURL } = user;
  const db = firebase.firestore();

  useEffect(() => {
    if (db) {
      const unsub = db
        .collection("messages")
        // .where("imgId", "==", selectedImgId)
        .orderBy("createdAt")
        .limit(100)
        .onSnapshot((snap) => {
          //show recent message
          const ulObj = document.getElementById("ulbox");
          ulObj.scrollTop = ulObj.scrollHeight;
          const data = snap.docs
            .map((doc) => ({ ...doc.data(), id: doc.id })) //Each child in a list should have a unique "key" prop.
            .filter((ele) => {
              return ele.imgId === selectedImgId; //extract messages for the selectedImg
            });
          if (data.length <= 10) {
            setMessages(data);
          } else {
            const lastTen = data.slice(data.length - 10, data.length);
            setMessages(lastTen);
          }
        });
      return unsub;
    }
  }, [db, selectedImgId]);

  const handleOnChange = (e) => {
    setNewMessage(e.target.value);
  };
  const handleOnSubmit = (e) => {
    e.preventDefault();

    if (db) {
      //make specific collection for each pircture!!
      db.collection("messages").add({
        text: newMessage,
        createdAt: timeStamp(),
        uid,
        displayName,
        photoURL,
        imgId: selectedImgId,
      });
    }
    setNewMessage("");
    // const inputBox = document.getElementById("inputBox");
    // inputBox.focus();
  };

 

이 메세지 데이터들은 아래와 같이 각 메세지 단위에 전달되어 렌더링 된다.

<Ulbox id="ulbox" style={{ listStyle: "none", paddingLeft: "0px" }}>
        {messages.map((message) => (
          <li id="libox" key={message.id}>
            <Message
              user={message}
              text={message.text}
              createdAt={message.createdAt}
            />
          </li>
        ))}
      </Ulbox>

 

2) submit new message

새 메세지를 제출하면 handleOnSubmit 함수를 통해 데이터베이스에 저장된다.

const handleOnSubmit = (e) => {
    e.preventDefault();

    if (db) {
      //make specific collection for each pircture!!
      db.collection("messages").add({
        text: newMessage,
        createdAt: timeStamp(),
        uid,
        displayName,
        photoURL,
        imgId: selectedImgId,
      });
    }
    setNewMessage("");
    // const inputBox = document.getElementById("inputBox");
    // inputBox.focus();
  };

3) user info (App.js)

현재 유저로 상태를 유지하되 변화가 생기면 새로운 user 로 상태를 저장하거나 null 로 설정한다.

  const [user, setUser] = useState(() => auth.currentUser);

  useEffect(() => {
    //this detects the change on state of user login
    const unsubscribe = auth.onAuthStateChanged((user) => {
      if (user) {
        setUser(user);
      } else {
        setUser(null);
      }
      if (initializing) {
        setInitializing(false);
      }
    });
    //cleanup subscription(the state of login of user to logout)
    return unsubscribe;
  }, [initializing, auth]);

이 user 라는 객체 안에 아래의 정보가 담기는데, uid/displayname/photoURL 은 자동으로 포함되어 있다.

Overview

오늘의 생각

파이어베이스를 활용한 부분(firestore/storage/auth(googlelogin)/deployment),

상태관리(createdAt/text/displayname/photoURL/imgId) 그리고 Framer-motion 활용법 등에 대한 코드리뷰를 해야겠다.

파이어베이스 기능들을 사용해보고자 3-4일 동안 진행했던 단기 프로젝트여서 조금 정신없이 코드를 짰던 것 같다.

필요한 부분이 있다면 로직 리팩토링도 해야겠다. 개괄적으로나마 파이어베이스를 백엔드 파트로 활용하는 법을 익힐 수 있었다.

 

가능하면, 그동안 진행했던 프로젝트들의 기능을 좀 더 손봐야겠다.

그리고, 내 포트폴리오 웹사이트를 하나 만들어야겠다.

 

추후 추가할 기능

  • 무한 스크롤
  • 채팅창에 접속 유저 표시
  • 메시지 입력중 말풍선 효과
  • 채팅창 첫 렌더시 최신 글이 먼저 보이도록 수정
  • 사진 저장 기능(버튼)
  • 카테고리 및 검색 기능

도움받은 사이트

파이어베이스 배포: youtu.be/IDHfvpsYShs