React - 쇼핑몰 구현 - Pages

그래도 아무튼 개발자·2023년 5월 22일
0

React / React-Native

목록 보기
6/6
post-thumbnail

주어진 더미 데이터 API를 활용하여 쇼핑몰을 구현하는 프로젝트이다.

구조

1. Main Page

1-1. Header
1-2. Product List
1-3. Bookmark List
1-4. Footer
1-5. Menu Bar

2. Product Page

2-1. Category
2-2. Product List

3. Bookmark Page

3-1 . Category
3-2. Bookmark List

4. Other

4-1. Toast
4-2. Bookmark

크게 위와 같이 구조를 잡고 프로젝트를 진행하였다.

App.js

import Header from "./components/Header";
import './App.css';
import Footer from "./components/Footer";
import MainPage from "./pages/MainPage";
import ProductList from "./pages/ProductList";
import BookmarkList from "./pages/BookmarkList";
import { Routes, Route } from 'react-router-dom';
import { useState } from "react";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";

function App() {
  const bookmarkRender = JSON.parse(localStorage.getItem("bookmark"));
  const [bookmarkState, setBookmarkState] = useState(bookmarkRender);
  return (
    <div className="App">
      <Header />
      <main>
        <Routes>
          <Route path="/" element={<MainPage 
                                    bookmarkState={bookmarkState}
                                    setBookmarkState={setBookmarkState}
                                  />} />
          <Route path="/product/list" element={<ProductList
                                            bookmarkState={bookmarkState}
                                            setBookmarkState={setBookmarkState}
                                           />} />
          <Route path="/bookmark" element={<BookmarkList 
                                            bookmarkState={bookmarkState}
                                            setBookmarkState={setBookmarkState}
                                            />} />
        </Routes>
      </main>
      <Footer />
      <ToastContainer position="bottom-right" />
    </div>
  );
}

export default App;

Other 기능 중 Toast 기능은 App의 제일 위에 올려져야 한 번만 실행되므로 App.js에 삽입하였다.

Pages(Main, Product, Bookmark)

Main Page

MainPage.js

import React, { useState, useEffect } from "react";
import MainListItems from "../components/MainListItems";
import MainBookmarkItems from "../components/MainBookmarkItems";
import axios from "axios";

const MainPage = () => {
  const [bookmarkState, setBookmarkState] = useState([]);
  const [itemList, setItemList] = useState([]);
  const url = "http://cozshopping.codestates-seb.link/api/v1/products?count=4";

  useEffect(() => {
    axios.get(url).then(res => {
      setItemList(res.data);
    });
  }, []);
  useEffect(() => {
    const storedBookmarks = JSON.parse(localStorage.getItem("bookmark")) || [];
    setBookmarkState(storedBookmarks);
  }, []);

  return (
    <main>
      <h2>상품 리스트</h2>
      <MainListItems
        itemList={itemList}
        bookmarkState={bookmarkState}
        setBookmarkState={setBookmarkState}
      />
      <h2>북마크 리스트</h2>
      <MainBookmarkItems
        bookmarkState={bookmarkState}
        setBookmarkState={setBookmarkState}
      />
    </main>
  );
};

export default MainPage;

ProductList.js

import React, { useState, useEffect } from "react";
import axios from "axios";
import ItemList from "../components/ItemList";
import "./ProductList.css"
import all from "./all.png";
import product from "./product.png";
import category from "./category.png";
import exhibition from "./exhibition.png";
import brand from "./brand.png";

const ProductList = ({ item, bookmarkState, setBookmarkState, isBookmarked }) => {
  const [itemListPage, setItemListPage] = useState([]);
  const [selectedType, setSelectedType] = useState("All");
  const url = "http://cozshopping.codestates-seb.link/api/v1/products";

  const handleIsBookmarked = item => {
    if (bookmarkState) {
      return bookmarkState.some(x => x.id === item.id);
    } else {
      return false;
    }
  };
  const handleSelectCategory = type => {
    setSelectedType(type);
  };
  useEffect(() => {
    axios.get(url).then(res => {
      setItemListPage(res.data);
    });
  }, []);

  const choose = [
    { img: all, name: "전체", type: "All" },
    { img: product, name: "상품", type: "Product" },
    { img: category, name: "카테고리", type: "Category" },
    { img: exhibition, name: "기획전", type: "Exhibition" },
    { img: brand, name: "브랜드", type: "Brand" },
  ];
  return (
    <div className="list">
      <div className="choose">
       {choose.map(category => (
         <div
           key={category.name}
           onClick={() => handleSelectCategory(category.type)}
         >
           <img src={category.img} alt={category.name} className="category" />
           <span>
             {category.name}
           </span>
         </div>
       ))}
      </div>
      <ul className="itemList">
        {
          itemListPage.filter(item => selectedType === "All" ? true : item.type === selectedType).map(item => {
            return (
              <ItemList
                key={item.id}
                item={item}
                isBookmarked={handleIsBookmarked(item)}
                bookmarkState={bookmarkState}
                setBookmarkState={setBookmarkState}
              />
            )
          })
        }
      </ul>
    </div>
  )
};

export default ProductList;

BookmarkList.js

import React, { useState, useEffect } from "react";
import axios from "axios";
import ItemList from "../components/ItemList";
import "./ProductList.css"
import all from "./all.png";
import product from "./product.png";
import category from "./category.png";
import exhibition from "./exhibition.png";
import brand from "./brand.png";

const BookmarkList = ({ item, bookmarkState, setBookmarkState }) => {
  const [itemListPage, setItemListPage] = useState([]);
  const [selectedType, setSelectedType] = useState("All");

  const url = "http://cozshopping.codestates-seb.link/api/v1/products";
  const handleIsBookmarked = item => {
    if (bookmarkState) {
      return bookmarkState.some(x => x.id === item.id);
    } else {
      return false;
    }
  };

  const handleSelectCategory = type => {
    setSelectedType(type);
  };
  useEffect(() => {
    axios.get(url).then(res => {
      setItemListPage(res.data);
    });
  }, []);


  const choose = [
    { img: all, name: "전체", type: "All" },
    { img: product, name: "상품", type: "Product" },
    { img: category, name: "카테고리", type: "Category" },
    { img: exhibition, name: "기획전", type: "Exhibition" },
    { img: brand, name: "브랜드", type: "Brand" },
  ];

  return (
    <div className="list">
      <div className="choose">
       {choose.map(category => (
         <div
           key={category.name}
           onClick={() => handleSelectCategory(category.type)}
         >
           <img src={category.img} alt={category.name} className="category" />
           <span>
             {category.name}
           </span>
         </div>
       ))}
      </div>
      <ul className="itemList">
        {
          bookmarkState.filter(item => selectedType === "All" ? true : item.type === selectedType).map(item => {
          return (
            <ItemList
              key={item.id}
              item={item}
              isBookmarked={handleIsBookmarked(item)}
              bookmarkState={bookmarkState}
              setBookmarkState={setBookmarkState}
            />
          );
        })}
      </ul>
    </div>
  )
};

export default BookmarkList;

상품리스트 화면과 북마크리스트 화면은 구조가 완전히 동일하다. 코드에서도 알수있듯이 거의 90% 흡사하게 코드가 짜여있다. 다만 북마크리스트는 말 그대로 북마크 버튼이 활성화가 되어있는 상품들만 들여와야 하기에, itemListPage가 아닌 bookmarkState를 이용하여 필터링을 해주고 있는 것을 확인할 수 있다.

녹화_2023_05_18_14_13_59_2-min

3개의 페이지가 결과물로 드러나 있는 화면이다. 다음 게시글에선 Pages를 제외한 각각의 Component 코드를 살펴보도록 하자.

0개의 댓글