상품의 상세 페이지 구현을 위해 DB에서 상세 정보를 가져오는 과정을 거쳐야한다. 구현은 다음 순서대로 진행된다.✊
상품 상세페이지의 url은 product url 뒤에 각각의 상품마다 부여될 유니크 아이디를 붙여 구성된다.
예를 들면 localhost:3000/product/123456abcdef
이런 식이다.
src/components/views/LandingPage/LandingPage.js 수정
function LandingPage() {
//...
const renderCards = Products.map((product, index) => {
return (
<Col lg={6} md={8} xs={24} key={index}>
<Card
cover={
<a href={`/product/${product._id}`}>
<ImageSlider images={product.images} />
</a>
}
>
<Meta title={product.title} description={`$${product.price}`} />
</Card>
</Col>
);
});
return (
//...
<Row gutter={[16, 16]}>{renderCards}</Row>
);
}
export default LandingPage;
디자인은 ant Design의 Card를 이용하고, 유니크 아이디는 product의 id로 부여된다. 해당 Card를 누르면 유니크 아이디와 일치하는 상품의 상세페이지로 이동하는 식이다.
위의 단계는 product._id가 붙은 링크로 이동하는 기능만 구현했을 뿐이고, 해당 유니크 아이디가 부여된 링크로 만들어진 페이지가 없기 때문에 오류가 난다. 따라서 path에 맞는 컴포넌트를 생성해주는 과정이 필요하다.
src/components/App.js 수정
import DetailProductPage from "./views/DetailProductPage/DetailProductPage";
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<NavBar />
<Switch>
// ..
<Route exact path="/product/:productId" component={Auth(DetailProductPage, null)} />
</Switch>
</div>
<Footer />
</Suspense>
);
}
유니크 아이디는 다 다르기 때문에 ":"를 표기 한다. :productId 를 통해서 path의 컴포넌트를 생성 후 접근하는 식이다.
src/components/views/DetailProductPage/DetailProductPage.js 생성
import React from "react";
function DetailProductPage() {
return <div>DetailProductPage</div>;
}
export default DetailProductPage;
그리고 상품의 상세 사항들을 띄워줄 상품 상세 페이지 컴포넌트를 생성해준다.
해당 상품에 대한 모든 정보들은 유니크 아이디를 이용해서 가져온다. 유니크 아이디와 일치하는 모든 정보들(타이틀, 이미지, 가격, 설명, 팔린 양,view 수 등)을 달라고 DB에 요청한다.
server/routes/product.js 수정
router.get("/products_by_id", (req, res) => {
//productId를 이용해서 DB에서 productId와 같은 상품의 정보를 가져온다.
let type = req.query.type;
let productId = req.query.id;
Product.find({ _id: productId })
.populate("writer")
.exec((err, product) => {
if (err) return res.status(400).send(err);
return res.status(200).send({ success: true, product });
});
});
productId에 대한 id는 쿼리스트링이기 때문에 req.query.~~ 의 형태로 받아주고 Product의 _id 중 ProductId와 일치하는 값을 find를 통해 찾아준다.
src/components/views/DetailProductPage/DetailProductPage.js 수정
import axios from "axios";
import React, { useEffect } from "react";
function DetailProductPage(props) {
const productId = props.match.params.productId;
useEffect(() => {
axios.get(`/api/product/products_by_id?id=${productId}&type=single`).then((response) => {
if (response.data.success) {
console.log(response.data);
} else {
alert("상세 정보 가져오기를 실패했습니다.");
}
});
}, []);
return <div>DetailProductPage</div>;
}
export default DetailProductPage;
get으로 productId를 보낸 뒤 일치하는 값이 있다면 해당 상품의 response를 우선 console.log 로 확인하는 형태로 구현해두었다. 여기서 props.match.params.productId는 router에서 상세페이지로 이동할 때 path를 :productId 의 형태로 넘겨주었는데 이 부분을 가져온다.
따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기 를 공부하며 작성한 글입니다.