React
[React] select 사용하여 option구현 (장바구니옵션)
jinist
2021. 12. 5. 10:59
하고자 하는 기능은
상품 데이터에 옵션이 있고, 옵션선택 시
옵션이 하단에 표시되고 count까지 할 수 있는 기능을 구현하려 한다.
const [selectedOption, setSelectedOption] = useState("");
const { id, name, price, image, description, option } = currentProduct;
//currentPropdoct에는 상품의 데이터가 담겨있다.
const haldleOptionSelect = (e) => {
setSelectedOption(e.target.value);
console.log(selectedOption); //선택된 옵션을 확인할 수 있다.
};
//..생략
<select onChange={haldleOptionSelect}>
<option value="">옵션을 선택해주세요</option>
{option.color.map((item, i) => (
<option value={item} key={i}>
{item}
</option>
))}
</select>
위와 같이 onChange과 useState를 사용하여 선택된 옵션을 알아낼 수 있다.
옵션이 선택되면 하단에 선택된 옵션들을 나열해주는 UI를 만들어야 한다.
const [selectedOption, setSelectedOption] = useState("");
const [selectedOptions, setSelectedOptions] = useState([]);
const haldleOptionSelect = (e) => {
setSelectedOption(e.target.value);
if (!e.target.value) {
return; // "옵션을 선택해주세요" 라는 옵션 선택 시 담기지 않게 처리
}
const selected = {
optionName: e.target.value,
quan: 1, // 수량의 기본값은 일단 1으로 주었다.
};
if (
selectedOptions.some((item) => item.optionName == selected.optionName)
) {
alert("이미 추가된 옵션입니다.");
// 이미 추가된 옵션을 다시 클릭했을 경우 알림창을 띄운다.
return;
}
setSelectedOptions([...selectedOptions, selected]);
// 선택된 옵션들을 담아준다.
};
//..생략
<select onChange={haldleOptionSelect}>
<option value="">옵션을 선택해주세요</option>
{option?.color.map((item, i) => (
<option value={item} key={i}>
{item}
</option>
))}
</select>
<ul className="selected-option-list">
{selectedOptions.length > 0 //selectedOptions에 값이 있을 때 노출하게 설정
? selectedOptions.map((item) => (
<li>
<span>{item.optionName}</span>
<span>{item.quan}</span>
</li>
))
: null}
</ul>
위와 같이 코드 작성 시 옵션 selected시 옵션 아래에
selectedOptions에 담은 각각의 optionName과 quan이 출력된다.
빈 값, 중복 값이 담기지 않게 처리까지 하였으니
추가된 값에 맞게 input을 만들어보자.
//..생략
const increase = (index) => {
const copy = [...selectedOptions];
copy[index].quan++;
setSelectedOptions(copy);
};
const decrease = (index) => {
const copy = [...selectedOptions];
if (copy[index].quan > 1) { // quan이 1 아래로는 떨어지지 않도록 한다.
copy[index].quan--;
setSelectedOptions(copy);
}
};
//..생략
<ul className="selected-option-list">
{selectedOptions.length > 0
? selectedOptions.map((item, index) => (
<li>
<span>{item.optionName}</span>
<button
className="plus-btn"
onClick={() => {
increase(index); //각각의 index를 전달해준다.
}}
>
+
</button>
<input type="tel" value={item.quan} />
// 해당 item의 quan의 값을 value로 설정
<button
className="minus-btn"
onClick={() => {
decrease(index);
}}
>
-
</button>
</li>
))
: null}
</ul>
해당 데이터의 quan에 맞게 input을 출력하는 것은 간단했지만
작업을 하다보니 메인 페이지에서 장바구니를 즉석에서 담는 기능을 작업할 때
해당 기능을 한번 더 쓸 듯 하여 hooks로 만들어서 관리하기로 했다.
//hooks
export const useOption = () => {
const [selectedOption, setSelectedOption] = useState("");
const [selectedOptions, setSelectedOptions] = useState([]);
const copy = [...selectedOptions];
const optionSelect = (e) => {
setSelectedOption(e.target.value);
if (!e.target.value) {
return;
}
const selected = {
optionName: e.target.value,
quan: 1,
};
if (
selectedOptions.some((item) => item.optionName == selected.optionName)
) {
alert("이미 추가된 옵션입니다.");
return;
}
setSelectedOptions([...selectedOptions, selected]);
};
const increase = (index) => {
copy[index].quan++;
setSelectedOptions(copy);
};
const decrease = (index) => {
if (copy[index].quan > 1) {
copy[index].quan--;
setSelectedOptions(copy);
}
};
return {
increase,
decrease,
optionSelect,
selectedOptions,
};
};