라디오 박스 필터 만들기
라디오 박스 필터는 CheckBox 필터 만드는 과정과 거의 비슷하기 때문에 복습할 땐 CheckBox 필터 글을 보자.
#1
RadioBox 리스트 데이터 만들기
Datas.js
const continents = [
{
"_id": 1,
"name": "Africa"
},
{
"_id": 2,
"name": "Europe"
},
{
"_id": 3,
"name": "Asia"
},
{
"_id": 4,
"name": "North America"
},
{
"_id": 5,
"name": "South America"
},
{
"_id": 6,
"name": "Australia"
},
{
"_id": 7,
"name": "Antarctica"
}
]
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
}
RadioBox를 위한 UI 만들기 & onChange Function 만들기 &
Checked State를 부모 컴포넌트로 업데이트 하기
Sections 폴더에 RadioBox.js 파일을 만든다.
https://ant.design/components/radio
RadioBox.js
import React, { useState } from 'react'
import { Collapse, Radio } from 'antd';
const { Panel } = Collapse;
function RadioBox(props) {
const [Value, setValue] = useState(0)
const renderRadioBox = () => (
props.list && props.list.map(value => (
<Radio key={value._id} value={value._id}>{value.name}</Radio>
))
)
const handleChange = (e) => {
setValue(e.target.value)
props.handleFilters(e.target.value)
}
return (
<div>
<Collapse defaultActiveKey={['1']}>
<Panel header="This is panel header 1" key="1">
<Radio.Group onChange={handleChange} value={Value}>
{renderRadioBox()}
</Radio.Group>
</Panel>
</Collapse>
</div>
)
}
export default RadioBox
위 코드에서 Radio.Gropup 컴포넌트는 모든 Radio 컴포넌트들을 감싸는 역할을 하므로 renderRadioBox 함수 자체를 감싸줘야한다.
Radio.Group 컴포넌트가 감싸는 Radio 컴포넌트들이 여러 개가 될 수 있다. 그 Radio 컴포넌트마다 value가 다르다.
Radio.Group 컴포넌트에 있는 value와 Radio 컴포넌트의 value가 같으면 이것이 클릭이 된 상태이다.
그래서 onChange 이벤트로 Radio.Group 컴포넌트의 value값을 컨트롤 하면 된다.
즉, Radio 컴포넌트를 클릭 할 때 마다 Radio.Group에 있는 handleChange Function이 작동하면서
Radio 컴포넌트에 있는 value가 Value State를 변경해서 Radio.Group 컴포넌트의 value값이 바뀌는 것이다.
이렇게 되면 라디오 컴포넌트는 오직 하나만 선택이 가능하게 된다.
#2
handleFilter Function 만들기
price 필터 같은 경우 continents 필터와 다른 것을 조금 넣어줘야 한다.
RadioBox 컴포넌트에서 선택한 라디오 박스의 value는 그 컴포넌트의 id값이 들어온다. 만약 두번째 라디오 박스를 선택했다면 filters 값으로 1이 들어갈 것이다.
CheckBox 컴포넌트 때 처럼 라디오 컴포넌트를 통해 필터링이 됐다면 바로 handleFilters 함수가 호출되면서 매개변수로 위에서 말했던 filters값과 'price' 카테고리가 들어갈 것이다.
handleFilter를 위한 handlePrice function 만들기
밑에 코드를 LandingPage.js 에 넣어주자.
const handlePrice = (value) => {
const data = price;
let array = [];
// 현재 data는 datas.js에서 갖고온 price 데이터들이 들어감
// 여기서 key는 0, 1, 2 ... 이런식으로 들어감
for (let key in data) {
// 매개변수로 받은 value는 price 필터의 filters 이다.
// 그리고 price 필터의 filters 데이터는 각 price 컴포넌트들의 id값들 즉, 0, 1, 2 ... 이다.
// parseInt로 감싸준 이유는 혹시라도 string이 들어오면 숫자로 바꿔주기 위해서이다.
if (data[key]._id === parseInt(value, 10)) {
array = data[key].array;
}
}
return array;
}
const handleFilters = (filters, category) => {
const newFilters = { ...Filters }
newFilters[category] = filters
if (category === 'price') {
let priceValues = handlePrice(filters)
newFilters[category] = priceValues
}
showFilteredResults(newFilters)
// setFilters를 통해 기존에 있던 contients 필터들과 바뀐 price 필터들을 새로 저장해주자.
setFilters(newFilters)
}
위 코드에서 주석으로 말했던 것처럼 RadioBox를 통해 필터링을 거치면 그때 받는 값은 _id값이다. 즉, Datas.js에서 정의해주었던 변수들의 _id값이므로 0, 1, 2, 3 이런식의 값이 들어간다.
여기서 handlePrice 함수가 하는 역할은 Datas.js에 있는 모든 price 변수를 반복문으로 탐색하면서 매개변수로 받은 _id값과 맞는 변수를 찾아서 그 변수의 배열 값을 리턴한다. 즉, [0, 199], [200, 249] 이런 식의 배열이 리턴된다.
이것을 'price'를 category 매개변수로 받은 handleFilters 함수에서 if문을 이용하여 newFilters['price'] = [handlePrice 함수를 통해 리턴된 배열값] 을 넣어주는 과정이다.
필터 기능을 위한 getProduct Route 수정하기
/products 라우트에서 반복문 부분을 조금 바꿔줘야 한다.
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];
}
}
}
price 필터같은 경우 handlePrice 함수를 통해 [0,199] 이런식의 배열값을 리턴했었다.
위 코드에서 price를 필터링 하는 과정일 때, findArgs['price'] = [0,199] 이런 식의 값이 들어가 있는 상태이다.
이때 0도 포함하고 199도 포함시켜주기 위해서 몽고DB에서 지원해주는 $gte, $lte를 이용하여 0과 199까지 포함시켜주는 과정이다.