컴포넌트가 로딩되었을 때 백엔드로 부터 meals 데이터를 받아 가져와야 한다.
fectch()
함수를 처음부터 사용해야 한다.useEffect()
를 사용하면 된다.그런데 fetch()
는 비동기 프로미스를 반환한다. then()
을 사용할 수도 있지만 async/await
을 사용하고자 한다면 아래 사항을 유의해야 한다.
useEffect( async () => {
await fetch("");
},[])
왜냐하면 useEffect로 입력한 함수는 실행 가능한 cleanup 함수를 반환할 수도 있기 때문이다.
클린업 함수는 동시에 실행해야 하는데 클린업 함수는 promise 같은 것을 반환하지 않는다.
따라서 useEffect에 입력한 전체 함수는 asnyc 함수로 변경해서는 안된다.
useEffect(() => {
// 중첩된 내부 함수를 새로 만들어 async/await 만들기
const fetchData = async () => {
await fetch("");
};
// 그리고 fetchData를 useEffect의 일부로 실행한다.
fetchData();
},[])
이렇게 하면 useEffect 함수 전체는 프로미스를 반환하지 않는다.
responseData는 객체로 저장되어 있다.
useEffect(() => {
const fetchMeals = async () => {
const response = await fetch(
"https://react-http-35c4a-default-rtdb.firebaseio.com/meals.json"
);
const responseData = await response.json();
//console.log(responseData);
//responseData는 객체로 저장되어 있다.
//데이터 변환
//for 반복문을 사용하여
//중첩 객체인 responseData를 빈 배열인 loadedMeals에 데이터를 가져오자.
const loadedMeals = [];
for (const key in responseData) {
loadedMeals.push({
id: key,
key: key,
name: responseData[key].name,
description: responseData[key].description,
price: responseData[key].price,
});
}
};
fetchMeals();
}, []);
가져온 데이터를 컴포넌트에 노출해야 한다.
비동기 태스크로 컴포넌트가 처음으로 로딩된 후에만 시작하기 때문에, 데이터를 가져오는 것이 완료되면 해당 컴포넌트를 다시 렌더링해야 한다.
따라서 처음에는 데이터가 없고, 데이터를 가져오면 컴포넌트가 변경되고 재평가해야한다.
이럴 때는 state가 필요하다.
import Card from "../UI/Card";
import MealItem from "./Meal/MealItem";
import classes from "./AvailableMeals.module.css";
import { useEffect, useState } from "react";
const AvailableMeals = () => {
//기본값으로 빈 배열을 넣어 오류가 나지 않게 하자.
const [meals, setMeals] = useState([]);
useEffect(() => {
const fetchMeals = async () => {
const response = await fetch(
"https://react-http-35c4a-default-rtdb.firebaseio.com/meals.json"
);
const responseData = await response.json();
//console.log(responseData);
const loadedMeals = [];
for (const key in responseData) {
loadedMeals.push({
id: key,
key: key,
name: responseData[key].name,
description: responseData[key].description,
price: responseData[key].price,
});
}
//데이터를 가져오면 상태에 넣어준다.
setMeals(loadedMeals);
};
fetchMeals();
//의존성 배열: 컴포넌트가 처음 로딩될 때만 실행하면 된다.
}, []);
//컴포넌트에 데이터 할당하여 렌더링되게 하기
const mealsList = meals.map((meal) => (
<MealItem
id={meal.id} // 각 인풋 컴포넌트가 개별적으로 인식되기 위해 id 넣는게 좋음
key={meal.id}
name={meal.name}
description={meal.description}
price={meal.price}
/>
));
return (
<section className={classes.meals}>
<Card>
<ul>{mealsList}</ul>
</Card>
</section>
);
};
export default AvailableMeals;