인프런 커뮤니티 질문&답변

황지호님의 프로필 이미지
황지호

작성한 질문수

[2024] 한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지

4.2) 첫 React App 생성하기

비동기 함수로 불러온 데이터를 화면에 렌더링

해결된 질문

작성

·

39

0

강의 내용을 바탕으로 프로젝트를 하나 만들다 안되는 부분이 있어 질문드립니다.

제가 axios를 이용해서 데이터를 받는 함수를 만들었는데요

 

const [posts, setPosts] = useState();

const getAllPosts = async () => { try{ const {data} = await axios.get("/api/posts"); console.log("axios - getAllPosts: ", data); setPosts(data); } catch(error){ console.log("getAllPosts 에러: ",error); } }

getAllPosts();

 

이런 코드를 작성했을때 렌더링할때 axios를 이용해서 받은 데이터를 posts란 state에 저장하고 이를 리스트 형태로 렌더링하려고 하는데 저기서 그냥 getAllPosts(); 를 해버리면 콘솔창에 무한하게 posts 값이 찍히고 화면에는 렌더링이 되지 않더라고요 ㅠ 콘솔창에는 그래도 데이터가 찍히긴 하는데 말이죠..ㅠ

getAllPosts메서드는 비동기 함수니깐 컴포넌트들이 렌더링되기 전에 실행되고 컴포넌트들이 렌더링되는거 아닌가요? 그럼 저 메서드를 호출하면 잘 렌더링이 되야하는거 아닌가요??ㅠㅠ

왜 저렇게 콘솔창에는 무한하게 데이터값이 찍히고 컴포넌트에는 왜 렌더링이 되지 않는건가요??

답변 2

0

이정환 Winterlood님의 프로필 이미지
이정환 Winterlood
지식공유자

안녕하세요 이정환입니다.

우선 전체 프로젝트의 코드를 확인할 수 없는 상황이며, 황지호님께서 개인적으로 진행하시는 프로젝트의 코드의 일부만 보고 답변드리는지라 정확한 문제 식별이 어려울 수 있다는 점 먼저 말씀드립니다.

전달해주신 정보로만 살펴봤을 때에 문제는 아마 아래 AI 인턴이 답변해 주었듯이 컴포넌트가 호출될 때 마다 getAllPosts 함수가 호출되고 있어서 그런 것 같습니다. useEffect를 활용해 컴포넌트 마운트 시점에 딱 한번만 해당 함수를 호출하도록 코드를 변경해보세요😃

PS. 추가로 코드가 일반 텍스트로 붙여넣어져서 보기가 힘드네요 ㅠㅠ 다음부터는 꼭 코드블럭 기능을 활용해 주시면 감사하겠습니다. (보는 입장에서는 많이 힘들어요 ...😭)

황지호님의 프로필 이미지
황지호
질문자

아 제가 그 부분은 생각하지 못하고 질문을 드렸네요ㅠㅠ 우선 답변 감사합니다!

답변 주신것처럼 useEffect를 통해 데이터를 받아왔는데 그 데이터를 가지고 렌더링이 안되고 있는 상황인데 혹시 이거는 어떻게 해결해야할지 아시나요??ㅠㅠ

api호출로 불러온 게시글들을 화면에 렌더링을 하고싶은데 밑의 코드처럼 작성하면 콘솔창에는 이제 데이터값이 한 번 찍히고 분명 여러개의 데이터들이 있는 배열 형태로 잘 찍히는데 화면에 렌더링하는 부분은 게시글이 없다고 뜹니다...

 

 

const [posts, setPosts] = useState();

const getAllPosts = async () => { // 모든 게시글들 불러오기
        try{
            const {data} = await axios.get("/api/posts");
            console.log("axios - getAllPosts: ", data);
            setPosts(data);
            // setIsLoading(false);
        } catch(error){
            console.log("getAllPosts 에러: ",error);
        }
    }

    useEffect(()=>{
        getAllPosts();
    },[])

return (
    <div className="list_wrapper">
       {posts === undefined ? ( 
           <p>게시글을 불러오는 중입니다...</p>
           ) : (posts.length > 0 ? ( 
           posts.map((post) => (
           <PostItem key={post.id} {...post} /> ))
           ) : (
           <p>게시글이 없습니다.</p> 
         ))}
     </div>
)
이정환 Winterlood님의 프로필 이미지
이정환 Winterlood
지식공유자

"게시글이 없습니다" 텍스트가 렌더링 되는거라면 아마 삼항 연산자의 조건 때문이겠군요 posts가 undefined 이거나 posts.length가 0 또는 0이하로 설정되는 것 같은데 이는 직접 확인해보셔야 할 문제인 것 같습니다.

충분히 정답을 스스로 찾으실 수 있는 문제인 것 같아요 프로젝트 전체 코드를 확인하지 못하는 제가 드릴 수 있는 가장 효과적인 조언은 State로 관리되며, 화면에 렌더링 해야 하는 데이터를 차분히 확실히 확인해보시라는 점을 꼭 말씀드리고 싶습니다.

0

안녕하세요, 인프런 AI 인턴입니다.

황지호님께서 질문하신 내용을 바탕으로 해결 방법을 안내드리겠습니다. 현재 작성하신 코드에서는 getAllPosts 함수를 컴포넌트의 렌더링 함수 내에서 직접 호출함으로써 무한 루프가 발생하고 있는 것으로 보입니다. 이는 리액트 컴포넌트가 렌더링될 때마다 getAllPosts 함수가 호출되기 때문입니다.

해결 방법은 useEffect 훅을 사용하여 컴포넌트가 처음 렌더링될 때 한 번만 데이터를 가져오도록 하는 것입니다. 다음은 올바른 코드 예시입니다:

import { useState, useEffect } from 'react';
import axios from 'axios';

const MyComponent = () => {
  const [posts, setPosts] = useState();

  const getAllPosts = async () => {
    try {
      const { data } = await axios.get("/api/posts");
      console.log("axios - getAllPosts: ", data);
      setPosts(data);
    } catch (error) {
      console.log("getAllPosts 에러: ", error);
    }
  }

  useEffect(() => {
    getAllPosts();
  }, []); // 빈 배열을 두 번째 매개변수로 넘겨주면 컴포넌트가 마운트될 때 한 번만 실행됩니다.

  return (
    <div>
      {posts ? (
        <ul>
          {posts.map(post => (
            <li key={post.id}>{post.title}</li>
          ))}
        </ul>
      ) : (
        <div>Loading...</div>
      )}
    </div>
  );
}

useEffect를 사용하여 특정 컴포넌트가 첫 번째 렌더링 시에만 getAllPosts() 함수가 호출되도록 설정합니다. 이로 인해 데이터 무한 반복 호출 문제를 해결할 수 있습니다.

또한, 데이터 로딩 동안 ‘Loading…’ 메시지를 표시하여 사용자에게 피드백을 제공할 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

황지호님의 프로필 이미지
황지호

작성한 질문수

질문하기