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

LeeGunWoo님의 프로필 이미지
LeeGunWoo

작성한 질문수

비전공자를 위한 진짜 입문 올인원 개발 부트캠프

상품 상세 페이지 구현 - 2

상품 정보를 받고 있습니다... 로 로딩만 되고 있어요! ㅠㅠ

작성

·

213

1

이렇게 상품을 클릭해서 넘어가면 이렇게 뜹니다. ㅠㅠ 
제가 어떤 부분을 잘못했는지 잘 모르겠어요! ㅠㅠ 

그래도 혹시 몰라 
소스코드들을 올려봅니닷 
[ App.css ] 

/* 기존에 있는 리엑트 CSS를 지우고  */
html, body, #root, #root > div{
  height: 100%;
}

#header{
  height: 64px;
  display: flex;
  justify-content: center;
  border-bottom: 1px solid grey;
}

#body{
  height: 100vh;
  width: 1024px;
  margin: 0 auto;
  padding-bottom: 24px;
}

#footer{
  height: 200px;
  background-color: rgb(230, 230, 230);
}


[ App.js ]

// import logo from './logo.svg';
import './App.css';

// import MainPage from './main/index.js'; >> ./main으로 해도 괜찮음!
import MainPage from './main';

import { SWitch, Route } from 'react-router-dom'
import ProductPage from './product';
import UploadPage from './upload';
import { Switch } from 'react-router-dom/cjs/react-router-dom.min';

function App() {
  return (
    <div>
      <div id="header">
        <div id="header-area">
          {/* <img src="images/icons/logo.png"/> // 간혹 스스코드를 작성했는데 안된다면 이미지 소스의 경로를 절대적으로 바꿔주면 된다. << 절대경로*/}
          <img src="/images/icons/logo.png"/>
        </div>
      </div>
      <div id="body">
        {/* 작성 방법_01 */}
        <Switch>
          <Route exact={true} path="/">
            <MainPage />
          </Route>
          <Route exact={true} path="/products/:id">
            <ProductPage />
          </Route>
          <Route exact={true} path="/upload">
            <UploadPage />
          </Route>
        </Switch>
      </div>
      <div id="footer"></div>
    </div>
  );
}

export default App;

 [ main > index.js ]

// 기존 우리가 작업했던 CSS를 연결해주기
// 그런데 문제가 있다 >> 따라서 App.css에서 수정을 해야 할 것들이 있다.  
import "./index.css"
import axios from "axios";
//axios 서버에서 가져오겠다는 뜻
import React from 'react';
//React
import {Link} from 'react-router-dom';
// Link를 뽑아 상품을 클릭 시 진행하도록 설정

function MainPage() {
   // return <p>MainPage</p>

   //React의 state로 상품정보에 대한 state이다.
   //state는 배열의 속성으로 우리는 useState([])로 빈 배열을 넣어줌.
   const [products, setProducts] = React.useState([]);

   //지속적인 업데이트를 통해 컴퓨터가 과부화가 생기지 않도록 React.useEffect를 활용한다. 즉 1번만 불러오고 정상적인 통신을 하는 것이다.
   React.useEffect(
      function () {
         //네트워크 postman에서 만든  MockServer의 product address를 가져오기
         axios.get('https://4326fdea-003a-4291-b8b3-b8e47b10723c.mock.pstmn.io/products')
            .then(function (result) {
               console.log(result);
               const products = result.data.products;
               setProducts(products);
               //지속적인 반복의 문제점을 해결!
            })
            .catch(function (error) {
               console.error("에러발생: ", error);
            });
      }, []
   )

   return (
      //// <div>를 하나 미리 만들어야 한다. 그리고서 Html > body에서 작성했던 모든 내용을 여기에 넣어준다.
      <div>
         {/* 여기서 이제 서버를 통한 product를 가져와야 한다. */}
         {/* <div id="header">
            <div id="header-area">
               <img src="images/icons/logo.png" />
            </div>
         </div>
         <div id="body"> */}
            <div id="banner">
               <img src="images/banners/banner1.png" />
            </div>
            <h1>판매되는 상품들</h1>
            <div id="product-list">
               {
                  products.map(function (product, index) {
                     // function(매개변수의 활용 > prodcut는 상품, index는 아이템 선택)
                     return (
                        <div className='product-card'>
                           {/* product-card, 즉 상품을 클릭 시 상품의 정보 페이지로 넘어갈 수 있도록 설정한다.
                           또한 React에서 Link를 통해 넘어는데 웹브라우저에서는 a태그로 보여준다. 즉, a태그로 변환이 되는 것을 확인할 수 있다. */}
                           {/* <Link className="product-link" to={'/products/' + index}> */}
                           {/* <Link className="product-link" to={`/products/ + ${index}`}> */}
                           {/* 0을 눌렀을 때, 1을 눌렀을 때 모두 다른 상품이 나오도록 index를 통해 활용 그리고 벡틱 작성법을 활용 */}
                           <Link className="product-link" to={`/products/ + ${product.id}`}>
                           <div>
                              <img className='product-img' src={product.imageUrl} />
                           </div>
                           <div className='product-contents'>
                              <span className='product-name'>
                                 {product.name}
                              </span>
                              <span className='product-price'>
                                 {product.price}
                              </span>
                              <div className='product-seller'>
                                 <img className='product-avatar' src='images/icons/avatar.png' />
                                 <span>
                                    {product.seller}
                                 </span>
                              </div>
                           </div>
                           </Link>
                        </div>
                     );
                  })
               }
            </div>
         {/* </div>
         <div id="footer">
         </div> */}
      </div>
   );

}

export default MainPage;
// MainPage를 내보내겠다는 뜻이다

 [ prodcut > index.js ]

import {useParams} from 'react-router-dom';
import axios from 'axios';
import { useEffect, useState } from 'react';

function ProductPage(){
   //const prams = useParams();
   // console.log(prams); //이제 상품을 선택을 할 때 콘솔창에 id: 0, 1, 2.. 상품 숫자가 나온다.
   
   const {id} = useParams();
   const [product, setProduct] = useState(null);
   //처음엔 null이 나타나고 렌더링이 되고 나서 서버에서 상품을 받아오고 호출됨.

   useEffect(function(){
      axios.get('https://4326fdea-003a-4291-b8b3-b8e47b10723c.mock.pstmn.io/products'+ id)
      .then(function(result){
         setProduct(result.data);
         // console.log(result);
      })
      .catch(function(error){
         console.log(error);
      })
   },[]);
   // console.log(product);
   // return <h1>상품 상세 페이지{id} 상품</h1> //js문법

   if(product == null){
      return <h1>상품 정보를 받고 있습니다...</h1>
   }

   return(
      <div>
         <div id="image-box">
            <img src={"/"+product.imageUrl}/>
            {/* const [product, setProduct] = useState(null); 를 비동기 처리방식으로 작동이 되기 때문에 당연히 product.imageUrl은 null로 처리가 된다. 따라서 오류가 발생이 되는 것은 당연한 원리이다.  */}
         </div>
         <div id="profile-box">
            <img src="/images/icons/avatar.png"/>
            <span>{product.seller}</span>
         </div>
      </div>
   );
}

export default ProductPage;

 

 postman에서 
 {{url}}/products의 주소

https://4326fdea-003a-4291-b8b3-b8e47b10723c.mock.pstmn.io

입니다 ㅠㅠ 

그리고 

GET prodcuts > Default 
 {

    "products" : [
            {
                "id" : 1, 
                "name": "농구공",
                "price": 10000,
                "seller": "로뎀",
                "imageUrl": "images/products/basketball1.jpeg"
            },
            {
                "id" : 2, 
                "name": "축구공",
                "price": 50000,
                "seller": "RockLee",
                "imageUrl": "images/products/soccerball1.jpg"
            },
            {
                "id" : 3, 
                "name": "키보드",
                "price": 15000,
                "seller": "테란황제",
                "imageUrl": "images/products/keyboard1.jpg"
            }
        ]
}

GET prodcuts/1

{
    "id": 1,
    "name": "농구공",
    "price": 10000,
    "seller": "로뎀",
    "imageUrl": "images/products/basketball1.jpeg",
    "description": "조던이 사용하던 농구공입니다"
}

죄송합니다 
제가 많이 부족해서 계속 물어보네요 ㅠㅠ 
계속 확인하고 확인해도 이번에는 어디서 문제가 있는지 모르겠어요ㅠ

 

 

 

답변 2

1

LeeGunWoo님의 프로필 이미지
LeeGunWoo
질문자

index.js 에서 벡틱을 쓸 때 + 를 붙여서 그랬나봐요! 
그런데 궁금한 것이 있는데 농구공 상품을 클릭을 할 때는 
농구공의 상품이미지가 잘 보이는데 
축구공과 키보드는 보이지 않네요 ㅠㅠ (이미지를 읽은 아이콘이 나와요) 

그랩님의 프로필 이미지
그랩
지식공유자

마찬가지로 Console로 확인을 해봐야 알 것 같아요!

현재 정상적으로 이미지를 가지고 있을까요?

1

그랩님의 프로필 이미지
그랩
지식공유자

현재 API 서버를 확인해봤을 때 잘 동작하는 것 같습니다.

개발자 도구에서 Console 창을 확인했을 때 어떤 로그들이 보이는지 확인해봐야 알 것 같습니다!

LeeGunWoo님의 프로필 이미지
LeeGunWoo
질문자

한번 해보겠습니다. 
Console 창 확인을 해보고 안된다면 
다시 글을 올리겠습니다! 

LeeGunWoo님의 프로필 이미지
LeeGunWoo

작성한 질문수

질문하기