비동기로 데이터 가져오기

이윤희·2025년 1월 10일

React/Next 일기

목록 보기
19/52

버튼을 누르면 비동기로 가져온 데이터를 기존 데이터 밑에 출력하고 싶어서 코드를 짰다.코드는 에러 없이 동작하는데(console에 데이터가 제대로?? 출력된 것 같음 아마도)

근데 눌러도 실제로 데이터가 표시되지 않음.

App.js

function App() {
  let [shoes, setShoes] = useState(data); //여기에 데이터가 들어있음
//중략
<>
              <div className="main-bg"></div>
              <div class="container ">
                <div className="row">
                  {shoes.map((a, i) => {
                    return <Product index={i} shoes={shoes} />;
                  })}
                </div>
              </div>
              <button onClick={()=>{
                axios.get('https://codingapple1.github.io/shop/data2.json')
                .then((result)=>{
                 
                  let cpy = [...shoes];

                  cpy.push(result); 
                  setShoes(cpy);
                  console.log(cpy);
                }
                  
                )
                .catch(()=>{
                  console.log('실패');
                })
              }}>버튼</button>
            </>
}

function Product(props) {

  return (
    <div class="col-md-4">
      <img src={props.shoes[props.index].img} width="80%" />
      <h4>{props.shoes[props.index].title}</h4>
      <p>{props.shoes[props.index].price}</p>
    </div>
  );
}

GPT

당신의 코드에서 데이터가 제대로 화면에 표시되지 않는 이유는 다음과 같습니다:


1. result 대신 result.data 사용 누락

axios로 데이터를 가져올 때, 결과는 result라는 객체 안에 저장되며 실제 데이터는 result.data에 있습니다. 현재 코드는 cpy.push(result)로 추가하고 있지만, result는 객체 전체이고 데이터를 포함한 배열은 result.data입니다.

cpy.push(result); // 잘못된 부분

이 부분을 수정하여 cpy.push(...result.data) 또는 cpy = [...cpy, ...result.data]와 같이 데이터를 제대로 추가해야 합니다.


2. Product 컴포넌트 렌더링 시 인덱스 접근

Product 컴포넌트는 props.shoes[props.index]를 통해 데이터를 접근합니다. 그러나 shoes 배열에 result.data가 제대로 추가되지 않으면 데이터가 화면에 반영되지 않습니다. 따라서 데이터가 올바르게 추가되는지 확인해야 합니다.


수정된 코드

다음은 문제를 해결한 수정된 코드입니다:

function App() {
  let [shoes, setShoes] = useState(data); // 초기 데이터

  return (
    <>
      <div className="main-bg"></div>
      <div className="container">
        <div className="row">
          {shoes.map((a, i) => {
            return <Product key={i} index={i} shoes={shoes} />;
          })}
        </div>
      </div>
      <button
        onClick={() => {
          axios
            .get("https://codingapple1.github.io/shop/data2.json")
            .then((result) => {
              let cpy = [...shoes, ...result.data]; // 데이터 병합
              setShoes(cpy); // 상태 업데이트
              console.log(cpy); // 콘솔에서 데이터 확인
            })
            .catch(() => {
              console.log("실패");
            });
        }}
      >
        버튼
      </button>
    </>
  );
}

function Product(props) {
  const product = props.shoes[props.index]; // 데이터 접근
  return (
    <div className="col-md-4">
      <img src={product.img} width="80%" />
      <h4>{product.title}</h4>
      <p>{product.price}</p>
    </div>
  );
}

주요 수정 사항

  1. result.data 사용:

    • axios 요청의 결과 데이터는 result.data에 저장되므로, cpy.push(...result.data) 또는 cpy = [...cpy, ...result.data]로 데이터를 추가해야 합니다.
  2. 상태 업데이트:

    • setShoes를 통해 상태를 업데이트하면 React가 컴포넌트를 다시 렌더링합니다.
  3. key 속성 추가:

    • shoes.map 내부에서 컴포넌트를 렌더링할 때 key를 설정해야 React가 각 항목을 구별하고 효율적으로 업데이트합니다.

데이터가 제대로 표시되는 이유

  1. 데이터를 올바르게 추가하면 setShoes를 호출하여 shoes 배열이 업데이트됩니다.
  2. React는 상태가 변경되었음을 감지하고 컴포넌트를 다시 렌더링합니다.
  3. Product 컴포넌트는 업데이트된 shoes 배열을 참조하며, 새로 추가된 데이터를 화면에 출력합니다.

여기서 알게 된 중요한 팁 두개

1. result 가 아니라 result.data를 다뤄야함!!!

result 안에는 Ajax 요청에서 딸려온 헤더라든가 불필요한 정보들이 많이 들어있음
내가 필요한 거를 쓰려면 그 안의 데이터에 접근해야함!
result.data 로...

2. [...a, b, c]

cpy = [...shoes, result.data]

이렇게 스프레드 문법으로 여러개를 같이 담을 수 있다!!!!
이렇게하면 한번에 데이터 합칠수 있으니 유용할 듯.


+ 추가

3. ...result.data

오류가 안 나고 버튼 누르면 공간이 생기는데 데이터가 계속 표시가 안 되길래 원인을 찾아봤다.

원인은 이녀석이었음

 let cpy = [...shoes, result.data];

내가 이렇게 넣었었다;;;

배열로 들어가 있어서, 그 배열이 하나짜리 취급 > map 돌았을 때 제대로 컴포넌트로 뱉어내지 못한 듯.??

result.data도 풀었어야 함!!!!!

let cpy = [...shoes, ...result.data];

이렇게 풀었어야 했다.

그리고 내가 여기서 cpy에 push(???)하려고했었는데 그것도 할필요가 없었다. 이미 저걸로 합쳤으니까...
+ push 가 아닌 이유 또 발견함
배열이랑 배열이니까 push 가 아니라 하려면 concat()을 했어야지!!ㅡㅡ


그래서 push 빼고 ...data 해서 해결.


++ 추가
버튼 몇 번 누르면 뭐 가져오고, 몇번 누르면 상품이 없다고 알려주는 코드를 짬.

let [clicked, setClicked] = useState('0');

<button onClick={()=>{
                clicked++;

                if(clicked == 1){
                  axios.get('https://codingapple1.github.io/shop/data2.json')
                  .then((result)=>{
                   
                    let cpy = [...shoes, ...result.data];
                    setShoes(cpy);
                  }
                  )
                  .catch(()=>{
                    console.log('실패');
                  })
                }
                else if(clicked == 2){
 		axios.get('https://codingapple1.github.io/shop/data3.json')
                  .then((result1)=>{
                    let cpy = [...shoes, ...result1.data];
                    setShoes(cpy);
                  })
                  .catch(()=>{
                    console.log('실패');
                  })
                } 
                
                if(clicked == 3){
                  alert('상품이 없습니다.');
                  console.log(clicked);
                }

                
              }}>버튼</button>

왜 안되지? 했는데

clicked++; <<<< 이녀석이 패인이었다!!!

변수가 아니라 state니까 state 변경함수를 썼어야 함.


덤으로

setClicked(clicked++); // 제대로 작동 안함
setClicked(++clicked); // 제대로 작동함

실행 순서 때문에 안 되는 것 같아서 바꿔줬더니 제대로 잘 된다.
clicked 를 먼저 증가시켜줘야 if문에 제대로 걸리는것~~

0개의 댓글