React.js 에서 http 작업하기 +

강정우·2023년 1월 12일
0

react.js

목록 보기
29/45
post-thumbnail
post-custom-banner

fetch와 useEffect

  • useEffect로 입력한 함수는 promise를 반환해서는 안 된다.
    왜냐하면 useEffect에 입력한 함수는 실행 가능한 cleanup 함수를 반환할 수 있기 때문이다.

  • 그런데 cleanup 함수는 동시에 실행해야 한다. 즉, promise나 이런 것은 반환하지 않고
    따라서 useEffect에 입력한 이 전체 함수는 async 함수로 변경해서는 안 된다.

  • useEffect 대신 async/await를 사용하고 싶다면 fetchMeals와 같은 새 함수를 이렇게 만들면 된다.
    그리고 async를 이곳에 사용하여 이 코드 줄을 중첩된 내부 함수로 입력한다. 그 다음 fetchMeal을 useEffect의 일부로 실행하면 된다

useEffect(() => {
  const fetchMeals = async () => {
    setIsLoading(true);
    const response = await fetch("https://react-http-e4fe2-default-rtdb.asia-southeast1.firebasedatabase.app1/meals.json");
    if(!response.ok){
      throw new Error("Something went wrong!");
    }
    const responseData = await response.json();
    const loadedMeals = [];
    for (const key in responseData) {
      loadedMeals.push({
        id: key,
        name: responseData[key].name,
        description: responseData[key].description,
        price: responseData[key].price
      });
    }
    setMeals(loadedMeals);
    setIsLoading(false);
  };

  try{                                    <= 여기서부터
    fetchMeals();
  } catch(err) {
    setIsLoading(false);
    setHttpError(err.message);
  }                                       <= 여기까지

}, [])

if (isLoading) {
  return <section className={classes.mealsLoading}>
    <p>Loading...</p>
  </section>
}

if (httpError) {
  return <section className={classes.mealsError}>
    <p>{httpError}</p>
  </section>
}
  • 그래서 위 code를 리뷰하자면 결과적으로 틀린코드이다. 바로 try catch문인데
    fetchMeals는 async 함수라는 사실을 명심해야 한다. 따라서 항상 promise를 반환한다.
    이제 promise 대신 오류를 가져오는 경우 그 오류로 인해 해당 promise가 거부하게 된다.
    따라서 try/catch를 사용해서 그것을 래핑 할 수 없다.
fetchMeals().then().catch((err)=>{
  setIsLoading(false);
  setHttpError(err.message);
});
  • 대신 await를 적용하여 useEffect 함수를 async 함수로 전환하면 가능하긴 한데 사실 이는 제일 위에서 언급했듯 clean-up함수를 반환해야하기 때문에 불가능하다.
  • 그래서 promise로 .catch() 메소드를 추가하면 이것이 promise를 반환하므로 then()을 추가할 수 있다.

즉, try-catch를 따로 구현하는 것이 아닌 그냥 fetchMeal 함수에 그냥 .then을 씌워서 async화 해주고 .catch 메서드로 처리하면 된다.

profile
智(지)! 德(덕)! 體(체)!
post-custom-banner

0개의 댓글