이제 동일하게 가격을 필터링하기 위한 라디오 박스 목차들을 만들려한다.
아래와 같은 순서로 진행된다.
src/components/views/LandingPage/Sections/Datas.js 수정
const price = [
{
_id: 0,
name: "Any",
array: [],
},
{
_id: 1,
name: "$0 to $199",
array: [0, 199],
},
{
_id: 2,
name: "$200 to $249",
array: [200, 249],
},
{
_id: 3,
name: "$250 to $279",
array: [250, 279],
},
{
_id: 4,
name: "$280 to $299",
array: [280, 299],
},
{
_id: 5,
name: "More than $300",
array: [300, 1500000],
},
];
export { continents, price };
앞서 체크박스에서 continents 데이터들을 넣었던 것과 마찬가지로 price 데이터들도 넣어준다.
array에는 price의 범위를 지정해서 첫번째 원소로는 필터의 시작점, 두번째 원소로는 필터의 끝점을 넣어준다.
src/components/views/LandingPage/LandingPage/Sections/RadioBox.js 생성 및 수정
import React, { useState } from "react";
import { Collapse, Radio } from "antd";
const { Panel } = Collapse;
const RadioBox = (props) => {
const [Value, setValue] = useState(0);
const renderRadioBoxLists = () =>
props.list &&
props.list.map((value) => (
<Radio key={value._id} value={value._id}>
{value.name}
</Radio>
));
const handleChange = (event) => {
setValue(event.target.value);
props.handleFilters(event.target.value);
};
return (
<Collapse defaultActiveKey={["1"]}>
<Panel header="This is panel header 1" key="1">
<Radio.Group onChange={handleChange} value={Value}>
{renderRadioBoxLists()}
</Radio.Group>
</Panel>
</Collapse>
);
};
우선 radioBox를 그리기 위한 RadioBox 관련 컴포넌트를 만들어준다. 해당 부분 또한 ant Design의 Radio와 panel를 사용하여 만들어진다.
radioBox 또한 checkBox와 마찬가지로 props의 list를 돌면서 Radio를 생성해준다.
panel을 통해서 접었다 폈다가 가능하도록 해주고, Radio.Group 안에 Radio 요소들을 그려주는 함수를 호출해준다.
src/components/views/LandingPage/LandingPage.js UI 수정
import { continents, price } from "./Sections/Datas";
import RadioBox from "./Sections/RadioBox";
function LandingPage() {
//...
return (
// ...
<Row gutter={[16, 16]}>
<Col lg={12} xs={24}>
{/* CheckBox */}
<CheckBox list={continents} handleFilters={(filters) => handleFilters(filters, "continents")} />
</Col>
<Col lg={12} xs={24}>
{/* RadioBox */}
<RadioBox list={price} handleFilters={(filters) => handleFilters(filters, "price")} />
</Col>
</Row>
)
}
export default LandingPage;
CheckBox가 왼쪽 RadioBox가 오른쪽에 배치되어야하기 때문에 Row와 Col을 사용해서 요소를 배치해주고 RadioBox의 props로 list에 price를 준다. 또한 handleFilter를 통해 price를 필터해준다.
src/components/views/LandingPage/LandingPage.js 수정
function LandingPage() {
//...
const handlePrice = (value) => {
const data = price;
let array = [];
for (let key in data) {
if (data[key]._id === parseInt(value, 10)) {
array = data[key].array;
}
}
return array;
};
const handleFilters = (filters, category) => {
const newFilters = { ...Filters };
newFilters[category] = filters;
console.log(filters);
if (category === "price") {
let priceValues = handlePrice(filters);
newFilters[category] = priceValues;
}
showFilteredResults(newFilters);
};
return (
//...
<CheckBox list={continents} handleFilters={(filters) => handleFilters(filters, "continents")} />;
)
}
export default LandingPage;
price의 경우 array의 형태로 필터링을 하고 있으므로 array를 받아주는 과정이 필요하기에 handlePrice 함수를 정의한다.
handleFilter의 경우에는 category가 price 인 경우 실행 할 함수들을 분기처리 해준다.
server/routes/product.js 수정
router.post("/products", (req, res) => {
// product collection에 들어있는 모든 상품 정보를 가져오기
let limit = req.body.limit ? parseInt(req.body.limit) : 20;
let skip = req.body.skip ? parseInt(req.body.skip) : 0;
let term = req.body.searchTerm;
let findArgs = {};
for (let key in req.body.filters) {
if (req.body.filters[key].length > 0) {
if (key === "price") {
findArgs[key] = {
//Greater than equal
$gte: req.body.filters[key][0],
//Less than equal
$lte: req.body.filters[key][1],
};
} else {
findArgs[key] = req.body.filters[key];
}
}
}
}
product router에서 price 관련한 부분을 위해 수정해준다. 해당 price는 array의 형태이므로 $gte와 $lte의 속성을 이용하여 값의 범위를 정해준 다음 필터링해주는 과정을 구현해준다. 결국 gte~lte 범위의 품목을 filter해서 findArgs 배열에 넣어주는 형태이다.
src/components/views/LandingPage/LandingPage.js 수정
const handleFilters = (filters, category) => {
setFilters(newFilters);
};
카테고리를 유저가 하나를 쓰는게 아니라 두개를 함께 쓰기 때문에 filter 부분에 continents와 price 필터를 같이 가지고 있어줘야 한다. 따라서 setFilters를 해주는 과정이 필요하다.
따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기 를 공부하며 작성한 글입니다.