2022.12.12 추가사항
"useReducer", "func.bind()" 를 사용하면 "REAL DOM" 에 "접근할 필요가 없겠구나"를 깨달음
1. [선택된 항목들]
useReducer 의 "ADD type"의 함수를 만들어 Array.concat() 새 배열을 만들어 추가되게만든다. (추가된 항목들의 배열)
2. [추가된 항목마다 달린 버튼들]
각 항목들은 Array.map() 을 사용하여 열거될것이다. 열거된 항목들마다, 각각의 버튼이 달릴 것이다.
3. [버튼들 각각의 함수]
각 버튼들은, function.bind() 의 부분적용을 사용하여, 각 id 파라미터를 고정시키고, 그에 맞는 배열의 amount 수정하는 함수를 만든다.
[종합]
concat 으로 추가된 배열은, 각 항목마다 버튼이 달리고, 그 버튼은 id 가 고정되어, 각 항목마다의 amount 만 바꾸는 로직을 가짐.
4. [ 최종 가격 ]
총 값은, Array.reduce() 를 사용한다. concat으로 추가된 배열(원 배열 말고) 의 각 amount 와 각 price를 곱해 최종 값이 나온다.
앞으로는 이렇게 하자
=============================================================================================='
<기존 방식> - 따라하지 마시오
React 는 Virtual DOM 을 이용하여, 필요한 부분만 변경하여 적용하는 방법을 사용합니다.
그래서 document.getElementById() 나, document.querySelector() 를 사용하지 않는 것을 권장합니다.
직접 DOM 에 접근하는 것은, REACT 의 생명주기와는 다른 시간에 적용이 될 뿐더러, 통제가 잘 되지 않기 때문입니다.
대신 useState 를 사용해 (혹은 useRef 지만 권장하지 않음), 상태를 통제합니다.
다만 현재, 무한으로 증가하는 값에 대해, 각각의 State 수를 통제하는 방법을 아직 알지 못해,
실제 DOM 에, querySelectorAll() 을 사용하여, 모든 값에 접근해, 더하는 방식을 사용하였습니다.
후에, "상태관리" 라이브러리 라던가, 상태관리에 대하여 더 배워야겠다
<계산기 로직>
<셀렉터 로직>
1. 카테고리를 누른다.
2. 카테고리에 알맞은 음식들이 나온다. ( Arrayt.filter() 를 사용한, 검색조건 활용)
3. 음식을 누르면, DB에서 칼로리를 가져온다.
4. 계산기 로직에 접근한다.
짜잔

코드를 봐보자
import styles from "./caculate-selector.module.css";
import { useState, useEffect } from "react";
import Button from "../ui/card/button";
function CaloireFoodSeletor(props) {
const { foodData } = props;
const [filteredData, setFilterdData] = useState([]); // 카테고리 선택하면, filter 되는 Data 정리
const [foodValue, setFoodValue] = useState(); // 음식을 눌렀을때, 그 음식에 대한 foodid 선택
const [foodInCalculator, setFoodInCalculator] = useState([]); // 총 누른 음식들의 Data를 Array 형태로 정리
const [totalCalories, setTotalCalorie] = useState(0);
const sortedFoodData = filteredData.sort((A, B) => // 전체 Data를 순서대로 정렬
A.name > B.name ? 1 : -1
);
useEffect(() => { // foodValue 가 바뀔때, [기존 + 새 foodid로 가져온 foodData] 를 삽입
if (foodValue) {
setFoodInCalculator((prev) => [
...prev,
foodData.find((food) => food.id === String(foodValue)),
]);
}
}, [foodValue]);
function resetHandler() { // [reset 로직]
setFoodInCalculator([]);
setTotalCalorie(0);
}
function filterFoodWithCategory(category) { // [필터링 로직] 카테고리 눌렀을때,
const filterd = foodData.filter((food) => food.category === category);
setFilterdData(filterd);
}
function calculate(e) { // [계산기 로직] 계산을 위해 DOM 에 접근
let foodCalorie = e.target.parentElement.children[2].children[0].value;
let quantity = e.target.parentElement.children[1].value;
let total = foodCalorie * quantity;
e.target.parentElement.children[3].children[0].value = Math.ceil(total);
const alltotals = document.querySelectorAll(".total");
let newArray = [];
for (const alltotal of alltotals) {
newArray.push(alltotal.value);
}
let totalCalories = newArray.reduce((sum, current) => +sum + +current);
setTotalCalorie(Math.ceil(totalCalories));
}
return (
<main className={styles.maindiv}>
<section className={styles.selector}>
<div>
<h2> 선택기 </h2>
<hr></hr>
<h4> 카테고리</h4> // 1 카테고리 선택
<hr></hr>
<ul className={styles.category}>
<li onClick={() => filterFoodWithCategory("다이어트")}>다이어트</li>
<li onClick={() => filterFoodWithCategory("한식")}>한식</li>
<li onClick={() => filterFoodWithCategory("양식")}>양식</li>
<li onClick={() => filterFoodWithCategory("일식")}>일식</li>
<li onClick={() => filterFoodWithCategory("베트남")}>베트남</li>
<li onClick={() => filterFoodWithCategory("중식")}>중식</li>
<li onClick={() => filterFoodWithCategory("디저트")}>디저트</li>
</ul>
<hr></hr>
</div>
<div>
<h4> 음식 </h4>
<hr></hr>
{filteredData && ( //2. 카테고리를 선택해, filteredData 가 생겼다면, 그 하위 음식들 선택
<ul className={styles.subSelector}>
{sortedFoodData.map((food) => (
<li
key={food.id}
value={food.id}
onClick={(e) => setFoodValue(e.target.value)}
>
{food.name}
</li>
))}
</ul>
)}
</div>
</section>
<section className={styles.calculator}>
<h2> 계산기</h2>
<hr></hr>
<div>
<ul className={styles.calculatorHeader}>
<li> 선택음식</li>
<li>
섭취량<span className={styles.unit}>x100g</span>{" "}
</li>
<li className={styles.caloriepergram}> 칼로리/100g</li>
<li> 총 칼로리</li>
</ul>
<hr></hr>
{foodInCalculator.map((food) => ( //3. 선택해놓은, 음식들의 데이터를 계산기에 생성
<ul key={food.id} className={styles.calculatorFoodList}>
<li>{food.name}</li>
<input
type={"number"}
step={1}
defaultValue={0}
onChange={(e) => calculate(e)}
className={styles.quantity}
/>
<li className={styles.caloriepergram}>
<input type={"number"} value={food.calorie} readOnly />
</li>
<li>
<input
type={"number"}
readOnly
className={"total"}
defaultValue={0}
/>
</li>
</ul>
))}
<hr />
<h4>총 칼로리</h4>
<div className={styles.totalCalories}>
<input type={"number"} value={totalCalories} readOnly />
<span> Kcal</span>
</div>
</div>
<div className={styles.buttondiv}>
<Button onClick={resetHandler}> 초기화 </Button>
</div>
</section>
</main>
);
}
export default CaloireFoodSeletor;
'메인-프로젝트 > Next.js - 오늘 뭐먹지? 프로젝트' 카테고리의 다른 글
10. 유저별 랜덤 선택기 구현하기 (0) | 2022.12.03 |
---|---|
9. 개인 유저 별 찜 기능을 구현해보자 (0) | 2022.12.03 |
7. 모든 음식들을, 카테고리 별로, 태그 별로 검색되도록 구현하자 (0) | 2022.12.02 |
6. 로그인 기능 구현 with Next-Auth (0) | 2022.12.02 |
0. 내가 React, Nextjs 를 선택한 이유 (0) | 2022.12.02 |
댓글