본문 바로가기

Projects/React + Firebase 링크드인 클론

#6. 피드와 포스트 입력창 구현 | Feeds, InputOption

메인 화면의 가운데 부분에 해당하는 Feed 컴포넌트를 구현하고자 한다. 이 Feed 컴포넌트 안에는 InputOption과 Post 컴포넌트가 존재한다. 

 

Feed 컴포넌트를 구현하기 위해서는 2가지 기능이 필요하다.

1) Input부분에 글을 작성하면, 작성자의 정보와 작성한 글이 DB에 저장되어야 한다. 이 때 DB는 Firebase를 활용한다.

2) 메인화면을 실행하면, 그동한 작성한 Post들을 불러와 Feed 부분에 띄워주어야 한다. Feed 컴포넌트 실행 시 작동하므로, React Hook 중 useEffect를 사용하도록 한다.

 

우선은 Feed.js를 구현한다.

 

import React, { useState, useEffect } from 'react'
import './Feed.css'
import CreateIcon from '@material-ui/icons/Create'
import InputOption from './InputOption'
import ImageIcon from '@material-ui/icons/Image'
import SubscriptionsIcon from '@material-ui/icons/Subscriptions'
import EventNoteIcon from '@material-ui/icons/EventNote'
import CalendarViewDayIcon from '@material-ui/icons/CalendarViewDay'
import Post from './Post'
import { db } from './firebase'
import firebase from 'firebase'
import { useSelector } from 'react-redux'
import { selectUser } from './features/userSlice'
import FlipMove from "react-flip-move"

function Feed() {

	//Redux에 저장된 user 정보를 Selectorfh 가져온다
    const user = useSelector(selectUser);
    
    //Input 창에 작성한 글을 관리할 State
    const [input, setInput] = useState('');
    
    //DB에 저장된 글들을 불러오기 위한 State
    const [posts, setPosts] = useState([]);

	//DB에 저장된 Post를 불러오는 부분. 추후에 자세히 설명
    useEffect(()=>{
        db.collection("posts").orderBy('timestamp', 'desc').onSnapshot((snapshot)=>
            setPosts(
                snapshot.docs.map((doc)=>({
                    id: doc.id,
                    data: doc.data()
                }))
            )
        );
    },[]);

	//Input 부분에 글을 작성하면, 그 내용을 저장하는 함수
    const sendPost = e => {
        e.preventDefault();

		//Firebase의 DB를 세팅. firebase.js 참조
        //DB 중에서 posts라는 collection에 작성한 글 저장
        db.collection("posts").add({
        
        	//작성한 사람이 누구인지, 그리고 글내용, 마지막으로 작성한 시간까지 함께 저장
            name: user.displayName,
            description: user.email,
            message: input,
            photoUrl: user.photoUrl || "",
            timestamp: firebase.firestore.FieldValue.serverTimestamp()
        });

        setInput("");
    };


    return (
    	//Feed 부분 전체를 담는 Div
        <div className="feed">
        
        	//글을 작성할 수 있는 Input 부분
            <div className="feed__inputContainer">
                <div className="feed__input">
                	//Material UI로 아이콘을 완성
                    <CreateIcon />
                    <form>
                    	//Input 창에 글을 작성하면, 그 내용을 Input 창에 바로 확인가능
                        <input type="text" value={input} onChange={e=>setInput(e.target.value)} />
                        
                        //Send 버튼을 누르면 작성한 글을 저장하는 함수 실행
                        <button type="submit" onClick={sendPost}>Send</button>
                    </form>
                </div>
                
                //Input 창 밑에 있는 상세 메뉴들
                <div className="feed__inputOptions">
                	//메뉴 아이콘과 메뉴명을 InputOption으로 보냄
                    //HeaderOption과 똑같음
                    <InputOption Icon={ImageIcon} title="Photo" color="#70B5F9" />
                    <InputOption Icon={SubscriptionsIcon} title="Video" color="#E7A33E" />
                    <InputOption Icon={EventNoteIcon} title="Event" color="#C0CBCD" />
                    <InputOption Icon={CalendarViewDayIcon} title="Write article" color="#7FC15E" />
                </div>
            </div>
            
            //지금까지 작성한 글(post)를 보여주는 부분. 추후에 자세히 설명
            <FlipMove>
                {
                    posts.map(({id, data:{name, description, message, photoUrl}})=>(
                    <Post
                        key={id}
                        name={name} 
                        description={description}
                        message={message}
                        photoUrl={photoUrl}
                    />
                    ))
                }
            </FlipMove>
        </div>
    )
}

export default Feed

Feed.js를 작성하였는데, Feed 컴포넌트 중에서도 글을 작성하는 기능을 우선 구현하였다. 글을 작성하면, 입력한 내용을 Input 창에서 바로바로 확인할 수 있도록 State를 사용하였다. 그리고 글을 작성한 뒤, 버튼을 누르면, 작성자가 누구인지와 함께 글의 내용을 DB에 저장할 수 있도록 Event Handling을 하였다. 이 때 DB는 Firebase 세팅 시 설정한 것이다.

 

Input창의 완성을 위해 InputOption.js도 작성한다.

import React from 'react'
import './InputOption.css'

function InputOption({Icon, title, color}) {
    return (
        <div className="inputOption">
        	//앞서 전달받은 아이콘과 메뉴명을 데이터바인딩한다
            <Icon style={{color:color}} />
            <h4>{title}</h4>
        </div>
    )
}

export default InputOption