728x90
반응형

이번엔 Firestore DB에서 데이터를 쿼리할겁니다.
쿼리한다는 뜻은 'DB에서 원하는 정보를 가져오는' 코딩을 말합니다.

components 밑으로 timeline.tsx를 만들어줍니다.
우선 기본적인 틀을 먼저 작성하고 interface를 만들어줄겁니다.

export interface ITweet {
    id: string;
    photo?: string;
    tweet: string;
    userId: string;
    username: string;
    createdAt: number;
}

export default function Timeline() {
	return <></>;
}

interface의 요소들은 이전에 작성한 폼 그대로 받아오면 되는데, firebase에서 확인 가능하고 각 자료형을 맞춰서 만들어줍니다.
photo는 있을수도 없을수도 있기에 처리해줍니다.

이후 tweets라는 배열을 만들어줄겁니다.

export interface ITweet {
    id: string;
    photo: string;
    tweet: string;
    userId: string;
    username: string;
    createdAt: number;
}

export default function Timeline() {
	const [tweets, setTweet] = useState<ITweet[]>([]);
	return <Wrapper>
    	{JSON.stringify(tweet)}
    </Wrapper>;
}

{JSON.stringify(tweet)} 이부분은 tweets를 우선은 문자로 나타내기 위해 작성합니다.
이후 tweet을 불러오기위해 fetch구문을 작성합니다.

export default function Timeline() {
    const [tweets, setTweet] = useState<ITweet[]>([])
    const fetchTweets = async () => {
        const tweetsQuery = query(
            collection(db, "tweets"),
            orderBy("createdAt", "desc")
        );
        const snapshot = await getDocs(tweetsQuery);
        const tweets = snapshot.docs.map((doc) => {
            const { photo, tweet, userId, username, createdAt } = doc.data();
            return {
                id: doc.id,
                photo, 
                tweet, 
                userId, 
                username, 
                createdAt
            }
        });
        setTweet(tweets);
    }
    useEffect(() => {
        fetchTweets();
    }, [])
    
	return <Wrapper>
    	{JSON.stringify(tweet)}
    </Wrapper>;
}

fetchTweets 라는 비동기 함수를 작성합니다.
collection을 이용해서 db의 tweets 값을 가져오고, orderBy를 사용해 최신순 정렬을 해줍니다.
getDocs를 이용해서 데이터를 가져오고 snapshot에 담은 후 map을 이용해서 순회하며 데이터를 가공하여줍니다.
이때,Id값은 다른 필드처럼 저장된게 아니기 때문에 doc.id로 저장합니다.
이후 가공된 값을 setTweets로 저장합니다.
함수실행을 위해 useEffect를 사용해줍니다.

여기까지 완료하고 home.tsx에 렌더링을 처리해야하기 때문에

import { styled } from "styled-components";
import PostTweetForm from "../components/post-tweet-form";
import Timeline from "../components/timeline";

const Wrapper = styled.div`
  display: grid;
  gap: 50px;
  overflow-y: scroll;
  grid-template-rows: 1fr 5fr;
`;

export default function Home() {
  return (
    <Wrapper>
      <PostTweetForm />
      <Timeline />
    </Wrapper>
  );
}

이와같이 작성해주고 게시글을 올려보면 JSON형태의 데이터가 렌더링된걸 보게됩니다.

components 밑으로 tweet.tsx를 만들어주고 코드를 작성합니다.

import styled from "styled-components";
import { ITweet } from "./timeline";
----------중략------------
export default function Tweet({username, photo, tweet}: ITweet) {
    return (
        <Wrapper>
            <Column> 
                <Username>{username}</Username>
                <Payload>{tweet}</Payload>
            </Column>
            {photo ? <Column>
                <Photo src={photo} />
            </Column>:null}
        </Wrapper>
    )
}

ITweet에서 username, photo, tweet만을 추출합니다.
이후 return을 작성해줍니다.

전체코드

import styled from "styled-components";
import { ITweet } from "./timeline";

const Wrapper = styled.div`
    display: grid;
    grid-template-columns: 3fr 1fr;
    padding: 20px;
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-radius: 15px;
`;

const Column = styled.div``;

const Photo = styled.img`
    width: 100px;
    height: 100px;
    border-radius: 15px;
`;

const Username = styled.span`
    font-weight: 600;
    font-size: 15px;
`;

const Payload = styled.p`
    margin: 10px 0px;
    font-size: 18px;
`;

export default function Tweet({username, photo, tweet}: ITweet) {
    return (
        <Wrapper>
            <Column> 
                <Username>{username}</Username>
                <Payload>{tweet}</Payload>
            </Column>
            {photo ? <Column>
                <Photo src={photo} />
            </Column>:null}
        </Wrapper>
    )
}

 

728x90
반응형