Firebase

Firebase를 사용한 트위터 클론 코딩#13(Preview Images)

PON_Z 2022. 8. 13. 19:49

- 이제 트윗에 이미지를 추가할 수 있도록 해보자.

  Home.js에 input에 트윗과 전송에 이어 파일을 추가할 수 있도록 하자.

        <form onSubmit={onSubmit}>
            <input
                value={tweet}
                onChange={onChange}
                type="text"
                placeholder="what's on your mind?"
                maxLength={120}
            />
            <input
             type="file"
             accept="image/*"
            />
            <input
                type="submit"
                value="Tweet"
            />
        </form>

- 아래와 같이 파일 선택을 누르면 이미지를 선택할 수 있다.

 

- 하지만 이미지를 미리보기할 수 없어서 불편하다. 미리보기 기능을 구현해보자.

  이를 위해 FIleReader API를 사용할 것이다.

  onFileChange 함수를 만들고 이를 파일선택에 적용시키자

  그리고 이미지를 띄우는 코드까지 작성했다.

// Home.js

import React, { useEffect, useState } from "react";
import { dbService } from "myFirebase";
import { addDoc, collection, getDocs, orderBy, query, onSnapshot } from "firebase/firestore";
import Tweet from "components/Tweet";

// for Home import
const Home = ({ userObj }) => {
    const [tweet, setTweet] = useState("");
    const [tweets, setTweets] = useState([]);
    const [attachment, setAttachment] = useState();

    const getTweets = async () => {
        const dbTweets = await getDocs(collection(dbService, "tweets"));
        dbTweets.forEach((document) => {
            // tweet의 구조
            const tweetObject = {
                ...document.data(),
                id: document.id,
            };
            setTweets((prev) => [tweetObject, ...prev]);
        });
    }

    const onSubmit = async (event) => {
        // 아무것도 입력하지 않는 행위 방지
        event.preventDefault();
        // tweets collction에 tweet내용과 작성시간을 담은 Doc을 add
        await addDoc(collection(dbService, "tweets"), {
            text: tweet,
            createdAt: Date.now(),
            creatorId: userObj.uid,
        });
        // add한 이후 tweet을 빈 문자열로 초기화
        setTweet("");
    };

    const onChange = (event) => {
        const {
            target: { value },          
        } = event;
        setTweet(value);
    };

    const onFileChange = (event) => {
        const {
            target:{ files },
        } = event;
        const theFile = files[0];
        const reader = new FileReader();

        // 파일 로딩이 끝남을 받는 event listener
        reader.onloadend = (finishedEvent) => {
            const {
                currentTarget: { result },
            } = finishedEvent;
            setAttachment(result);
        }
        reader.readAsDataURL(theFile);
    };


    useEffect(() => {
        //getTweets();
        const q = query(collection(dbService, "tweets"), orderBy("createdAt", "desc"));
        // arr를 만들어준다음 setTweets 하는 방법
        onSnapshot(q, (snapshot) => {
            // snapshot은 listener라고 생각하면 됨
            const tweetArr = snapshot.docs.map((document) => ({
                id: document.id,
                ...document.data(),
            }));
            setTweets(tweetArr);
        })
    }, []);

    return (
        <div>
        <form onSubmit={onSubmit}>
            <input
                value={tweet}
                onChange={onChange}
                type="text"
                placeholder="what's on your mind?"
                maxLength={120}
            />
            <input
                type="submit"
                value="Tweet"
            />
            <input
                onChange={onFileChange}
                type="file"
                accept="image/*"
            />
            {
                attachment &&
                <img src={attachment} width="100px" height="100px" />
            }
        </form>
        <div>
            {tweets.map((tweet) => (
                <Tweet key={tweet.id}
                       tweetObj={tweet}
                       isOwner={tweet.creatorId === userObj.uid}
                />
            ))}
        </div>
    </div>
    );
};    

export default Home;

 

- 아래와 같이 업로드한 이미지가 보이게 되었다.

 

- 이제 업로드한 이미지를 지우고 싶을 수 있으므로 clear 버튼을 만들어 주자

  onClearAttachment 에서 attachment state를 null로 만들고 버튼 클릭시

  적용되도록 하자

 

  const onClearAttachment = () => setAttachment(null);
            {
                attachment && (
                <div>
                    <img src={attachment} width="100px" height="100px" />
                    <button onClick={onClearAttachment}>Clear</button>
                </div>
                )
            }
 

- clear 버튼을 누르면 이미지가 사라진다.

 

 

- ref) https://nomadcoders.co/nwitter/lectures/

728x90