상품 업로드 페이지의 대략적인 부분을 만들어보자!✊
아래와 같은 순서로 진행된다.
components/views/LandingPage/LandingPage.js 생성
import React from "react";
function LandingPage() {
return <div>LandingPage</div>;
}
export default LandingPage;
우선은 랜딩 페이지를 구현 할 컴포넌트 하나를 만들어주자!
server/routes/product.js 수정
router.post("/products", (req, res) => {
// product collection에 들어있는 모든 상품 정보를 가져오기
Product.find()
.populate("writer")
.exec((err, productInfo) => {
if (err) return res.status(400).json({ success: false, err });
return res.status(200).json({ success: true, productInfo });
});
});
DB에서 데이터를 가져 올 라우터를 생성해준다. /products라는 이름의 post 형식의 라우터를 생성하고 안에 작업을 해준다.
우선은 필터 박스가 없기 때문에 모든 DB의 상품을 가져오기 위해서 find 메서드를 조건없이 호출해준다. 이후 필터가 생기면 해당 메서드 안에 price 등의 조건을 넣어 조건에 해당하는 데이터만 가져올 수 있다.
등록한 사람의 이름 이미지, 이메일 주소 등이 다 필요하기 때문에 아이디를 이용해서 writer의 모든 정보를 가질 수 있도록 populate를 해준다. populate는 다른 다큐먼트의 ObjectId를 쓰기위해 해주어야하는 작업이고 해당 작업을 통해 writer에 대한 role의 정보,id 등이 들어있다.
exec 쿼리를 돌렸을 때 실패하면(status 400) success: false와 함께 error를 반환하고, 성공하면(status 200) 해당 productInfo를 반환해준다.
components/views/LandingPage/LandingPage.js 수정
import React, { useEffect } from "react";
import axios from "axios";
function LandingPage() {
const [Products, setProducts] = useState([]);
useEffect(() => {
axios.post("/api/product/products").then((response) => {
if (response.data.success) {
console.log(response.data);
setProducts(response.data.productInfo);
} else {
alert("상품들을 가져오는데 실패 했습니다.");
}
});
}, []);
return <div>LandingPage</div>;
}
export default LandingPage;
DB에 저장되어있는 데이터를 가져오기 위해 axios를 사용해준다.
/api/product/products라는 엔드 포인트에서 주는 response의 data 안에 DB에 저장되어있는 데이터가 있다. 가져온 데이터들은 setProducts 를 이용해 Products에 저장해준다.
components/views/LandingPage/LandingPage.js 수정
import React, { useEffect, useState } from "react";
import axios from "axios";
import { Icon } from "antd";
function LandingPage() {
// ...
return (
<div style={{ width: "75%", margin: "3rem auto" }}>
<div style={{ textAlign: "center" }}>
<h2>
Let's Travel Anywhere
<Icon type="rocket" />
</h2>
</div>
{/* Filter */}
{/* Search */}
{/* Cards */}
</div>
);
}
export default LandingPage;
우선은 이런 식으로 대략적인 디자인과 들어가야할 것들의 위치를 잡아준다.
components/views/LandingPage/LandingPage.js 수정
import React, { useEffect, useState } from "react";
import axios from "axios";
import { Button, Icon, Col, Card, Row } from "antd";
import Meta from "antd/lib/card/Meta";
function LandingPage() {
// ...
const renderCards = Products.map((product, index) => {
console.log(product);
return (
<Col lg={6} md={8} xs={24} key={index}>
<Card
cover={
<img style={{ width: "100%", maxHeight: "200px" }} src={`http://localhost:5050/${product.images[0]}`} />
}
>
<Meta title={product.title} description={`$${product.price}`} />
</Card>
</Col>
);
});
return (
<div style={{ width: "75%", margin: "3rem auto" }}>
<div style={{ textAlign: "center" }}>
<h2>
Let's Travel Anywhere
<Icon type="rocket" />
</h2>
</div>
{/* Filter */}
{/* Search */}
{/* Cards */}
<Row gutter={[16, 16]}>{renderCards}</Row>
</div>
);
}
export default LandingPage;
이후에는 AntD의 Card를 이용해서 이미지 카드를 만들어준다.
우선 이미지 카드를 그릴 renderCards라는 함수를 정의해준다.
map을 이용해서 Products에서 product item 하나 하나에 대한 Card 컴포넌트를 그려준다. card 에 띄워줄 이미지 커버에 대한 스타일과 이미지의 위치에 대한 부분들을 정의해준다. Card의 Meta에는 아래에 띄워줄 이미지의 타이틀과 가격을 적어준다.
함수 구현이 끝났으면 카드를 그려줄 때 Row의 gutter를 이용해서 그리드에 알맞게 그려준다.
components/utils/ImageSlider.js 생성 및 구현
import React from "react";
import { Carousel } from "antd";
function ImageSlider(props) {
return (
<div>
<Carousel autoplay>
{props.images.map((image, index) => (
<div key={index}>
<img style={{ width: "100%", maxHeight: "150px" }} src={`http://localhost:5050/${image}`} />
</div>
))}
</Carousel>
</div>
);
}
export default ImageSlider;
이제 마지막으로 이미지가 자동으로 넘어가는 슬라이더 기능만 구현하면 끝난다!
슬라이더를 어떻게 구현하지 했는데 antD에서 제공해주는 기능을 사용해서 쉽게 구현할 수 있다. antD carousel을 이용해서 구현을 해보자.
우선 이미지 슬라이더는 랜딩 페이지 이외의 곳에서도 사용할 수 있으니 utils 폴더에 ImageSlider.js 파일을 생성해서 구현해주었다.
랜딩 페이지에서 정의해놓은 이미지는 props로 내려받아주고 이미지의 스타일 속성과 src를 map을 사용해 이미지 하나하나 속성을 부여해준다. 그리고 슬라이더가 자동으로 돌아갈 수 있게 autoplay 속성을 부여해준다.
components/views/LandingPage/LandingPage.js 수정
import ImageSlider from "../../utils/ImageSlider";
const renderCards = Products.map((product, index) => {
console.log(product);
return (
<Col lg={6} md={8} xs={24} key={index}>
<Card cover={<ImageSlider images={product.images} />}>
<Meta title={product.title} description={`$${product.price}`} />
</Card>
</Col>
);
});
landingpage에서는 카드를 그려주는 renderCards 함수만 수정하면 된다. ImageSlider를 import해오고 카드의 커버 부분에 ImageSlider 를 넣고 images props로 이미지 사진을 하위 컴포넌트로 내려주자!🔥
이렇게 하면 슬라이더까지 구현 완료이다. 이제 카드가 로드될 수 있도록 더보기 버튼을 구현하고, 필터 기능, 검색 기능만 구현하면 된다!✨
따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기 를 공부하며 작성한 글입니다.