개요
- 백엔드 API 를 통해서 데이터베이스에 저장된 데이터를 Load 해보자.
- AllMeetupPage 에 해당 컴포넌트가 렌더링 될 때마다 Http request 을 보내서 Load 해야 한다.
- 페이지를 열 때 마다 요청을 보내서 데이터를 가져오게 해야 한다.
NewMeetups.js
import MeetupList from "../component/meetups/MeetupList";
import {useState} from "react";
function AllMeetupsPage() {
const [isLoading, setIsLoading] = useState(true);
const [loadedMeetups, setLoadMeetups] = useState([]);
fetch(
'<https://database-default-rtdb.firebaseio.com/meetups.json>'
).then(response => {
return response.json();
}).then(data => {
setIsLoading(false);
setLoadMeetups(data);
});
if (isLoading) {
return (
<section>
<p>Loading...</p>
</section>
);
}
return (
<section>
<h1>All Meetups</h1>
<MeetupList meetups={loadedMeetups} />
</section>
);
}
export default AllMeetupsPage;
- fetch 는 프로미스를 반환하기 때문에 then 메소드를 사용하면 된다.
- response 객체를 인자로 반환 받을 수 있다.
- response 객체를 json() 를 통해 일반 자바스크립트 객체로 변환할 수 있다.
- 하지만 json 도 프로미스를 반환하기 때문에 return 시키고 then 메소드를 사용하여 실제 데이터를 받아왔다. (예외 핸들링도 가능)
- 이제 MeetupList 컴포넌트의 meetups prop 으로 해당 데이터를 전달하면 된다.
- 문제는 fetch 가 프로미스를 반환한다는 것이다.
- 자바스크립트는 프로미스가 완료될 때까지 기다리지 않는다.
- async 와 await 을 사용하여 완료될 때까지 기다리게 한다면 전체 컴포넌트 함수가 프로미스를 반환하게 된다.
- 리액트에 컴포넌트 함수들은 반드시 동기식이어야 하며, JSX 코드를 반환해야 한다.
- 그러므로 우리는 로딩 스피너와 같은 임시 JSX 코드를 반환해야 한다.
- 그런 다음 응답을 받으면 반환 된 JSX 코드를 업데이트 한다.
- useState 훅을 사용하여 상태 주어 해결 하였다.
state
- state 를 사용하면 상태가 변경될 때 마다 컴포넌트를 재실행하여 화면 내용을 다시 렌더링 한다.
- 문제는 우리가 request 을 할 때마다 상태를 바꾸고 있는데, 바꾸면 컴포넌트 함수가 재실행된다.
- 그러면 fetch 함수가 다시 실행되고, request 을 다시 하게 되고, 또 다시 상태를 바꿀 것이다.
- 무한 루프가 생성되면서 애플리케이션이 중단될 것이다.
- 이 문제는 useEffect 훅으로 해결할 수 있다.
useEffect
import MeetupList from "../component/meetups/MeetupList";
import {useEffect, useState} from "react";
function AllMeetupsPage() {
const [isLoading, setIsLoading] = useState(true);
const [loadedMeetups, setLoadMeetups] = useState([]);
useEffect(() => {
setIsLoading(true);
fetch(
'<https://database-default-rtdb.firebaseio.com/meetups.json>'
).then(response => {
return response.json();
}).then(data => {
const meetups = [];
for (const key in data) {
const meetup = {
id: key,
...data[key]
};
meetups.push(meetup);
}
setIsLoading(false);
setLoadMeetups(meetups);
});
}, []);
if (isLoading) {
return (
<section>
<p>Loading...</p>
</section>
);
}
return (
<section>
<h1>All Meetups</h1>
<MeetupList meetups={loadedMeetups} />
</section>
);
}
export default AllMeetupsPage;
- useEffect 훅은 특정 조건을 만족하면 일부 코드를 실행하는 훅이다.