-
OnlineShop 만들기 - 8) Product Detail Page 만들기1 (상품 이미지, 상품 설명란 만들기)NODE.JS 2021. 5. 15. 23:24
상품에 대한 디테일 정보를 나타내는 페이지를 만들 것이다.
상품 사진란과 설명을 하는 란 2가지로 나위어서 진행한다.
views>DetailProductPage>DetailProductPage.js파일을 만든다.
import React from 'react' function DetailProductPage() { return ( <div> </div> ) } export default DetailProductPage
우선 app.js에 route를 만들어준다.
import DetailProductPage from './views/DetailProductPage/DetailProductPage'; //아무나 상세페이지 확인 가능하도록 null로 만들어준다. <Route exact path="/product/:productId" component={Auth(DetailProductPage, null)} />
우리는 이미 랜딩페이지에서 카드를 누르면 다음의 링크로 (productId) 이동하도록 설정해놨다.
const renderCards = Products.map((product, index) => { return <Col lg={6} md={8} xs={24}> <Card hoverable={true} //링크 누르면 다음의 주소로 이동한다. cover={<a href={`/product/${product._id}`} > <ImageSlider images={product.images} /></a>}//이미지가 애니메이션 형식으로 옆으로 이동하도록 설정 > <Meta //상품 이름하고 가격이 나오도록 한다. title={product.title} description={`$${product.price}`} /> </Card> </Col> })
디테일 프로덕트 페이지에 다음과 같은 문장을 추가해준다.
(axios 보내기)
import React,{useEffect} from 'react' function DetailProductPage() { //링크타고 들어온 주소에 이미 productId 가 있으므로 이것을 이용한다. const productId = props.match.params.productId useEffect(() => { //이렇게 하는 이유는 get을 해서 가져올때는 쿼리를 이렇게 넣는다. Axios.get(`api/product/products_by_id?id = ${productId}&type = single`) .then(response=>{ }) }, [])
axios를 보냈으니 router를 생성한다.
router.get("/products_by_id", (req, res) => { let type = req.query.type //이번에는 쿼리로 가져왔기 때문에 body가 아닌 쿼리를 사용한다. let productIds = req.query.id if(type =="array"){//타입이 배열이라서 여러개를 가져온다면 다음과 같이 처리한다(여기서 우리는 single로 가져와서 상관 없다.) } //we need to find product information that belong to product Id Product.find({'_id':{$in:productIds}}) //아이디에 해당하는 모든 정보 받을 수 있다 ($in) .populate('writer') .exec((err, product)=>{ if(err) return res.status(400).send(err); return res.status(200).send(product) }) });
다음과 같이 정보를 받아오면 처리해준다.
function DetailProductPage() { //링크타고 들어온 주소에 이미 productId 가 있으므로 이것을 이용한다. const productId = props.match.params.productId const [Product, setProduct] = useState([])//Axios에서 받아온 상품에 대한 정보를 받는다. useEffect(() => { //이렇게 하는 이유는 get을 해서 가져올때는 쿼리를 이렇게 넣는다. 여기서 single은 우리가 원하는 프로덕트 디테일이 1개이기 때문에 넣은 것이다.(아이디 하나만 넣는다)여러가지라면 type =array Axios.get(`api/product/products_by_id?id = ${productId}&type = single`) .then(response=>{ setProduct(response.data[0])//res에 담긴 product 1개의 정보만 받아와서 세팅한다. }) }, [])
이제 디테일 페이지의 템플릿을 작성하는데,
우리는 이미지를 나타낼 때, react-image-gallery를 사용하므로 client에
npm install react-image-gallery --save를 해준다.
https://www.npmjs.com/package/react-image-gallery
return ( <div className="postPage" style={{ width: '100%', padding: '3rem 4rem' }}> <div style={{ display: 'flex', justifyContent: 'center' }}> <h1>{product.title}</h1> </div> <br /> <Row gutter={[16, 16]} > <Col lg={12} xs={24}> ProductImage </Col> <Col lg={12} xs={24}> ProductInfo </Col> </Row> </div> ) }
여기서 상품 이미지를 나타내는 파일과 세부정보를 나타내는 파일을 sections 폴더 안에 각각 만들어 줄 것이다.
DetailProductPage>Sections>ProductImage.js
DetailProductPage>Sections>ProductInfo.js파일을 각각 생성해준다.
다음과 같이 디테일 페이지에 import 해준다.
그다음 상품에 대한 정보를 각각 props로 넣어준다.
import React,{useEffect, useState} from 'react' import Axios from 'axios' import { Row, Col } from 'antd'; import ProductImage from './Sections/ProductImage'; import ProductInfo from './Sections/ProductInfo'; <Row gutter={[16, 16]} > <Col lg={12} xs={24}> <ProductImage detail = {Product}/> </Col> <Col lg={12} xs={24}> <ProductInfo detail = {Product}/> </Col> </Row> export default DetailProductPage
productImag.js파일로 가서 image gallery를 import 해주고 템플릿을 만들어준다.
@import "~react-image-gallery/styles/css/image-gallery.css";
import React,{useEffect, useState} from 'react' import ImageGallery from 'react-image-gallery'; function ProductImage(props) { const [Images, setImages] = useState([]) useEffect(() => { //이미지가 있고 1개이상 존재한다면 if(props.detail.images && props.detail.images.length>0) { let images = []; //오리지날은 슬라이드하면서 보여주는 큰 사진이고, 썸네일은 아래 보이는 작은 보기들이다. props.detial.images && props.detail.images.map(item =>{ images.push({ original: `http://localhost:5000/${item}`, thumbnail: `http://localhost:5000/${item}` }) }) setImages(images) } }, [props.detail])//우리가 이미지를 가져우기 위해서 dom이 로드 되었을 때 우리가 props.detail을 가져오지 못하면 실행이 안되므로, props.detial이 가져와 졌을 때 이것을 실행한다는 의미이다. (props.detial이 변경되었으면 useEffect가 다시 실행될 것이다. ) return ( <div> {/* image gallery를 이용해서 이미지들을 넣을 것이다. */} <ImageGallery items= {Images}/> </div> ) } export default ProductImage
이제 product info 부분을 만들자.
antd를 사용할 것이다.
import React, { useEffect, useState } from 'react' import { Button, Descriptions } from 'antd'; function ProductInfo(props) { const [Product, setProduct] = useState({})//Product 정보 가져와서 담을 것이다. useEffect(() => { setProduct(props.detail)//상품정보 가져와서 셋팅 }, [props.detail])//있을 때 실행(변경되거나 존재할때 실행) return ( <div> {/* 상품들의 정보를 가져온다. */} <Descriptions title="Product Info"> <Descriptions.Item label="Price"> {Product.price}</Descriptions.Item> <Descriptions.Item label="Sold">{Product.sold}</Descriptions.Item> <Descriptions.Item label="View"> {Product.views}</Descriptions.Item> <Descriptions.Item label="Description"> {Product.description}</Descriptions.Item> </Descriptions> <br /> <br /> <br /> <div style={{ display: 'flex', justifyContent: 'center' }}> <Button size="large" shape="round" type="danger" onClick > Add to Cart </Button> </div> </div> ) } export default ProductInfo
css 스타일링을 주기 위해서 index.css에 다음과 같이 추가한다.
table { font-family : arial, sans-serif; border-collapse: collapse; width: 100%; } td, th { border: 1px solid #dddddd; text-align: left; padding: 8px; } tr:nth-child(even){ background-color: #dddddd; }
'NODE.JS' 카테고리의 다른 글
OnlineShop 만들기 - 10) Cart Page 만들기 1 (cart정보 가져오기) (0) 2021.05.16 OnlineShop 만들기 - 9) Product Detail Page 만들기2 (Add to cart 기능 만들기) (0) 2021.05.16 OnlineShop 만들기 - 7) Landing Page 만들기 4(Search feature 만들기) (0) 2021.05.15 OnlineShop 만들기 - 6) Landing Page 만들기 3(check 필터링, price 필터링 만들기) (0) 2021.05.15 OnlineShop 만들기 - 5) Landing Page 만들기 2(loadmore 버튼) (0) 2021.05.15