import { useSelector, useDispatch } from "react-redux";
import Stack from "@mui/material/Stack";
import Button from "@mui/material/Button";
import { decreaseCount, increaseCount } from "../store/cart/cartSlice";
import { selectCartTotal } from "../store/cart/cartSlice";
function Cart() {
const dispatch = useDispatch();
const list = useSelector((state) => state.cart);
const total = useSelector(selectCartTotal);
const handelPlus = (id) => {
dispatch(increaseCount(id));
};
const handelMinus = (id) => {
dispatch(decreaseCount(id));
};
return (
<Stack spacing={2} direction="column" margin={5} alignItems="center">
{list.map((data) => (
<Stack key={data.id} spacing={2} margin={5}>
<div>{"상품 이름: " + data.title}</div>
<div>{"가격: " + data.price}</div>
<Stack spacing={2} direction="row">
<Button variant="outlined" onClick={handelPlus(data.id)}>
+
</Button>
<div>{"갯수: " + data.count}</div>
<Button variant="outlined" onClick={handelMinus(data.id)}>
-
</Button>
</Stack>
</Stack>
))}
<div>상품 총액: {total}</div>
</Stack>
);
}
export default Cart;
위와 같이 작성했더니 화면이 동작하지 않게되었습니다...
버튼 클릭 시 함수가 즉시 호출되는 형태로 작성
-> 이를 해결하기 위해서는 콜백 함수를 사용하여 이벤트 핸들러를 올바르게 작성해야 합니다.
<Button variant="outlined" onClick={()=>handelMinus(data.id)}>
-
</Button>
콜백함수로 변경!
onClick={handelPlus(data.id)}
는 함수를 직접 호출하는 것입니다.
onClick={()=>handelPlus(data.id)}
는 콜백 함수로 작성한 것입니다.
직접 호출
콜백
클로저 문제 피할 수 있음
클로저 예시상황
반복문 안에서 이벤트 핸드러를 등록할 때 직접호출을 사용하게 되면 반복문의 마지막 값만을 참조하게 됨
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
위의 결과는 5가 5번 출력되게 된다.
이유?
setTimeout 함수 내부의 콜백 함수가 외부 함수인 for 루프의 변수 i에 접근하기 때문입니다. setTimeout 함수는 비동기적으로 실행되는데, 콜백 함수가 실제로 실행되는 시점은 for 루프가 이미 완료된 이후입니다. 따라서 setTimeout 함수 내부의 콜백 함수는 for 루프가 종료된 후에 실행되며, 이때 i의 값은 이미 5가 되어있습니다.
해결!
for (var i = 0; i < 5; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
}, 1000);
})(i);
}
콜백함수로 작성해주면 됩니다.
이벤트 리스너(event listener)와 콜백함수(call back function)
[JavaScript]Callback vs Promise 자바스크립트 콜백함수 vs 프로미스 예시, 비교
콜백과 이벤트
생활코딩 댓글
클로저
[JavaScript] 클로저 (Closure)
킹받네요!