만두의 부트캠프 🤔
  • [Day4] 4-2. ItemCard 만들기
    2023년 12월 17일 01시 51분 31초에 업로드 된 글입니다.
    작성자: 만두33

     

    📋 구현목표

    • 가장 작은 단위인 ItemCard를 먼저 만들어준다.
    • ItemCard에 서버의 데이터를 넣어준다.
    • ItemCard의 CSS를 적절하게 수정한다.

    # ItemCard 컴포넌트 만들기

    ✔️ ItemCard.jsx 파일 만들기

    컴포넌트 폴더 안에 만들어준다.

    export default function ItemCard(){
        return <div>ItemCard</div>;
    }

    기본 코드 입력한다.

    export default 구문은 이 함수형 컴포넌트를 다른 파일에서 불러와 사용할 수 있도록 내보내는 역할.


    ✔️ MainPage.jsx 기본코드

    export default function MainPage() {
      return <main>Main Page</main>;
    }

     

    기본코드안에 ItemCard.jsx를 넣어준다.

    import ItemCard from '../components/ItemCard';
    
    export default function MainPage() {
      return (
        <main>
          <ItemCard/>
        </main>
        );
    }

     

    이렇게하면! 화면에 ItemCard가 나타난다는 것을 알 수 있다!

     


    # Constants.js , apiService.js 만들기

    이제 모든 상품 정보를 서버에서 가지고 올 예정이다.

    서버에서 가지고 오기위해서 파일을 먼저 따로 만들어준다!

    ✔️ 각각 파일을 생성한다.

    ✔️ Constants.js 코드

    export const API_URL = 'https://cozshopping.codestates-seb.link/api/v3';

     

    ✔️ apiService.js코드

    import { API_URL } from './Constantsonstants';
    
    export const fetchData = (endpoint) => {
      return fetch(API_URL + endpoint).then((res) => res.json());
    };

    * 코드설명

    더보기
    • import { API_URL } from './Constantsonstants';는
      다른 파일에서 내보낸 API_URL 상수를 현재 파일로 가져오겠다는 의미입니다.

    • export const fetchData = (endpoint) => {...}는
      fetchData라는 함수를 다른 파일에서 사용 가능하도록 내보내겠다는 의미입니다.
      이 함수는 API_URL과 endpoint를 조합하여 해당 엔드포인트에 대한 데이터를 가져오는 역할을 합니다.
      fetch 함수를 사용하여 비동기적으로 데이터를 가져옵니다.

    # ItemCard.jsx에 해당하는 데이터 서버에서 불러오기

    이부분이 내가 아직 완전히 이해를 못하고, 코드를 짜기 어려워 하는 부분이라는걸 알았다!

    레퍼런스 코드를 보고 참고해서 작성했다.

    구조적으로 보면 아래그림이다.

    1. 서버에서 필요한 데이터를 ItemCard.jsx에 가지고 온다.
    2. CategoryBox.jsx안에 여러개의 ItemCard들을 모아준다. (.map 사용)

    저번 코드에서는 ItemCard.jsx 한곳에서 .map까지 다 해줘서 코드가 엉망이 되어버렸다.

    구조적으로 작게 구분을 해놓고 기능별로 사용을 해주자!

     

    ✔️ Main.js 코드

    // MainPage.jsx
    import React, { useState, useEffect } from 'react';
    import { fetchData } from '../apiService';
    import CategoryBox from '../components/CategoryBox';
    
    export default function MainPage() {
      const [items, setItems] = useState([]);
      const [selectedCategoryId, setSelectedCategoryId] = useState(0);
    
      useEffect(() => {
        setItems([]);
        fetchData(
          `/products?limit=12&${
            selectedCategoryId > 0 ? `category=${selectedCategoryId}` : ""
          }`,
        ).then((data) => setItems(data.items));
      }, [selectedCategoryId]);
    
      return (
        <main>
          <CategoryBox items={items} />
        </main>
      );
    }

     

     

    ✔️ ItemCard.jsx 코드

    //ItemCard.jsx
    import React from 'react';
    
    export default function ImageCard({ imageUrl, title, price }) {
      return (
        <div className="item_card">
          <img src={imageUrl} alt={title} />
          <div>{title}</div>
          <p>{price}원</p>
        </div>
      );
    }

     

    ✔️ ItemCard.jsx 코드

    //CategoryBox.jsx
    import React from 'react';
    import ItemCard from './ItemCard';
    
    export default function CategoryBox({ items }) {
        return (
            <div className="items_container">
                {items.map((item) => (
                    <ItemCard
                        key={item.id}
                        imageUrl={item.imageUrl}
                        title={item.title}
                        price={item.price}
                    />
                ))}
            </div>
        );
    }

     


    # CSS 수정하기

    저번 코드에서는 CSS도 뒤죽박죽이었다.

    Styledcomponent를 사용했었는데 너무 복잡해져서 이번엔 사용하지 않고

    최대한 App.css 한곳에서 CSS를 수정할것이다.

     

    ✔️ App.css 코드

    /* App.css */
    header {
      height: 8vh;
      background: white;
      display: flex;
      align-items: center;
      position: sticky;
      top: 0;
      box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
      justify-content: space-around;
      flex-wrap: wrap;
    }
    
    .logo_container {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 1rem;
    }
    
    .logo_container>img {
      width: 2.5rem;
    }
    
    header>label {
      display: flex;
      gap: 1rem;
      background: white;
      padding: .5rem 1rem;
      border-radius: 1rem;
      border: 1px solid blue;
    }
    
    header>label>input {
      border: none;
    }
    
    header>label>input:active {
      outline: none;
    }
    
    main {
      /* height: 92vh; */
      height: auto;
      overflow-y: scroll;
      overflow: hidden;  
      align-items: center;
      border: 3px solid red;
      padding: 16px;
    }
    
    
    footer {
      background-color: lightgray;
      display: flex;
      justify-content: center;
      padding: 2rem;
      gap: 2rem;
      flex-direction: column;
      align-items: center;
    }
    
    footer>nav {
      display: flex;
      gap: 1rem;
    }
    
    .item_card {
      display: flex;
      flex-direction: column; 
      flex-wrap: wrap;
      align-items: center;
      width: 300px ;
      height: 500px ;
      white-space: pre-wrap;
      overflow: hidden;  
      border: 1px solid blue;
      padding: 10px;
    }
    
    .item_card img {
      max-width: 90%; 
      max-height: 80%; 
      border-radius: 5px;
      margin: 10px auto;
      width: 300px ;
      height: 450px;
      text-align: center;
    
    
    }
    
    .items_container {
      display: flex;
      flex-wrap: wrap;
      flex-shrink: 1;
      align-items: center;
      text-align: center;
      overflow-x: auto;
      border: 2px solid yellow;
    }

     

    Main의 height를 auto로 하면 메인 영역이 끝나면 자동으로 footer가 메인의 끝 범위에 생성된다.

    ItemCard.jsx는 <div className="item_card"> ,

    CategoryBox.jsx는 <div className="items_container"> 으로 클래스 이름을 주고 App.css에서 일괄적으로 수정했다.

    기타 높이, 넓이, 줄바꿈, 외곽선, 등등등 요소들을 설정해준 현재 화면

     

    대략적으로 다 설정한것 같은데... 저 우측의 틈이 자꾸 남는다 ㅠㅠ

    해결하는법

    App.css 코드에서 .items_container 안에 아래 코드를 추가해준다.

      justify-content: space-around;

     

    여기까지 구현화면

     


    🫠👏

    댓글