<Wrapper>
<PostTweetForm />
<Timeline />
</Wrapper>
Timeline 파일을 생성해서 home에 태그로 사용해준다.
const Wrapper = styled.div`
overflow-y: scroll;
`;
기존에 생성한 업로드 버튼과 textarea를 고정시키고 타임라인만 슬라이드 하기위해 작성
const [tweet, setTweet] = useState<ITweet[]>([]);
React에 이건 tweet 배열이고 기본값은 빈배열이라고 알려준다.
return <Wrapper>
{JSON.stringify(tweets)}
</Wrapper>;
tweets를 문자로 출력
const fetchTweets = async() => {}
fetchTweets라는 비동기함수 생성
useEffect(() => {
fetchTweets();
}, []);
useEffect를 사용해서 fetchTweets호출
import { query } from "firebase/firestore";
const fetchTweets = async() => {
const tweetsQuery = query();
}
firebase에서 query import 해서 쿼리 만들어주기
컬렉션을 대상으로 지정해주기(어떤 컬렉션을 쿼리하고 싶은지 정하기 ==> tweets)
tweets는 firebase에 등록된 폴더
orderBy("createdAt", "desc")
createdAt 을통해 내림차순(최신순) 으로 정렬하기
const snapshot = await getDocs(tweetsQuery);
document 가져오기( getDocs() )
snapshot.docs.forEach(doc => console.log(doc.data()));
forEach를 사용해서 각 문서에 접근하고 문서데이터를 출력
쿼리의 snapshot을 받아서 쿼리에서 반환된 각 문서 내부의 데이터를 log로 출력
log가 두번출력되는데 이유는
useEffect(() => {
fetchTweets();
}, []);
개발모드에서 react.js가 useEffect를 두번 호출하기 때문
const tweets = snapshot.docs.map(doc => {
const {tweet, createdAt, userId, username, photo} = doc.data();
});
.map사용 map내의 함수에서 반환한 학목을 가지고 배열을 생성해준다.
ITweet을 만족하는 모든데이터 추출
return {
tweet, createdAt, userId, username, photo
,id : doc.id
}
추출한 모든 객체를 반환
id는 문서에 다른 필드처럼 저장되어있지 않음, id : doc.id 로 아이디값 지정해주기
setTweet을 이용해서 추출한 트윗들의 상태를 저장해준다.
import { ITweet } from "./timeline";
export default function Tweet({}:ITweet){}
tweet글을 작성해줄 파일을 하나 생성한다
Tweet은 이전파일에서 생성한 ITweet 인터페이스를 받는다.
export interface ITweet {
id : string;
photo? : string;
tweet : string;
userId : string;
username : string;
createAt : number;
}
사진파일이 없을 수 도 있기때문에 ? 를 붙여준다.
export default function Tweet({ username, photo, tweet }: ITweet) {
return (
<Wrapper>
<Column>
<Username>{username}</Username>
</Column>
<Column>
<Payload>{tweet}</Payload>
</Column>
{photo ? (
<Column>
<Photo src={photo} />
</Column>
) : null}
</Wrapper>
);
}
모든 프로퍼티 추출
{tweets.map(tweet => <Tweet key={tweet.id} {...tweet} />)}
이전파일에서 db값을 가져온다
트윗마다 Tweet 컴포넌트를 렌더링, key값은 트윗의ID
unsubscribe = await onSnapshot(tweetsQuery, (snapshot) => {
const tweets = snapshot.docs.map((doc) => {
const { photo, tweet, userId, username, createAt } = doc.data();
return {
photo,
tweet,
userId,
username,
createAt,
id: doc.id,
};
});
setTweet(tweets);
});
Firestore DB에서 실시간으로 쿼리의 변경사항을 수신하게 하기
문서를 한번만 가져오는 대신 쿼리에 리스너를 추가하는것
무언가 delete, update, insert되었다는 알림을 받으면 해당 쿼리의 문서를 확인하고 필요한 데이터를 추출
추출한 데이터를 map을 이용해서 배열로 만든다.
onSnapshot 함수는 unsubscribe(구독취소)함수를 반환한다.
fetchTweets 을 useEffect() 안에서 작성해준다
https://firebase.google.com/docs/firestore/query-data/listen#view_changes_between_snapshots
Cloud Firestore로 실시간 업데이트 가져오기 | Firebase
Demo Day를 위해 일정을 비워두고 Firebase의 새로운 소식과 기능들을 확인해 보세요. 자세히 알아보기 의견 보내기 Cloud Firestore로 실시간 업데이트 가져오기 컬렉션을 사용해 정리하기 내 환경설정
firebase.google.com
let unsubscribe : Unsubscribe | null = null;
unsubscribe의 타입은 unsubscribe 또는 null , 처음에는 null값을 가지고있다.
unsubscribe변수에 구독취소함수를 저장
return () => {
unsubscribe && unsubscribe();
}
useEffect에서 값을 반환할 때 unsubscribe함수를 호출한다
unsubscribe가 True라면(null이 아니라면) unsubscribe호출
==> useEffect의 tear down, cleanup 기능을 사용
유저가 해당 컴포넌트가 보이지 않을 때( 타임라인 컴포넌트가 보이지 않을때 ) cleanup 실행
페이지네이션 기능을 추가해서 25개의 글만 출력하기( tweetsQuery )