useCartProducts
hook 사용validProducts
에 저장validProducts
데이터를 selectedItems
에 저장해서 페이지에 접근했을때 상품이 선택된 상태로 보여줌useEffect에서 cartProducts
와 validProducts
와 데이터가 변경되면 상태를 업데이트 하도록 처리하는 과정에서 무한루프가 발생함
// CartList.tsx
****
const { cart, removeSelectCart, toggleCart, updateCartIsBuy } = useCart();
const { cartProducts, isError } = useCartProducts(cart);
const [validProducts, setValidProducts] = useState<(Cart & Product)[]>([...cartProducts.filter((item) => item.productQuantity !== 0)]);
const { selectedItems, setSelectedItems, toggleItemSelection, toggleAllItemSelection } = useSelection(validProducts);
useEffect(() => {
setValidProducts([...cartProducts.filter((item) => item.productQuantity !== 0)]);
}, [cartProducts])
useEffect(() => {
setSelectedItems(validProducts.map((item) => item.id))
}, [validProducts])
원인 : cartProducts
배열이 변경될 때마다 useEffect
가 실행되는데 cartProducts.filter()
메서드를 호출하면 항상 새로운 배열이 생성되기 때문에 이 배열의 참조값이 변경되어 무한 루프가 발생
해결 : 의존성 배열을 cartProducts 배열 자체가 아니라 cartProducts.cartProducts로 변경해 배열의 길이가 변경될 때만 감지하도록 함
useEffect(() => {
const validItems = cartProducts.filter((item) => item.productQuantity !== 0);
setValidProducts(validItems);
}, **[cartProducts.length]**);
tosspayments로 결제를 완료 하면 successUrl로 지정한 페이지로 이동하게 된다.
결제 성공 화면에서 처리할 작업
buyProducts
저장payment
저장 mutateAddOrder
에 전달해 주문 정보 저장mutateAddOrder
를 호출하는 useEffect
에서 무한 루프 발생
// PaymentSuccess.tsx
const { cart } = useCart();
const buyProducts = (item) => item.isBuy);
const { user } = useAuth();
const [searchParams] = useSearchParams();
const userId = user?.uid;
const orderId = searchParams.get('orderId');
const amount = Number(searchParams.get('amount'));
if (!userId || !orderId || !amount) return
const payment = { userId, orderId, amount }
const { mutate: mutateAddOrder } = useAddOrder();
useEffect(() => {
if (!payment || !buyProducts.length) return;
const processOrder = async () => {
await mutateAddOrder({ payment, buyProducts });
};
processOrder();
}, [payment, buyProducts, mutateAddOrder]);
원인 : useEffec
의 종속성 배열에 객체를 넣으면 무한 루프 문제가 발생
→ 얕은 비교를 통해 참조 값이 변경되었는지 확인하는데 렌더링할 때마다 객체의 참조 값이 변경되므로 useEffect
가 다시 실행됨
해결 : useMemo를 사용해서 렌더링 중에 상태의 참조 값이 변경되지 않도록 함
const { cart } = useCart();
**const buyProducts = useMemo(() => cart.filter((item) => item.isBuy), [cart]);**
const { user } = useAuth();
const [searchParams] = useSearchParams();
const userId = user?.uid;
const orderId = searchParams.get('orderId');
const amount = Number(searchParams.get('amount'));
**const payment = useMemo(() => {
return userId && orderId && amount ? { userId, orderId, amount } : null;
}, [userId, orderId, amount]);**
const { mutate: mutateAddOrder } = useAddOrder();
useEffect(() => {
if (!payment || !buyProducts.length) return;
const processOrder = async () => {
await mutateAddOrder({ payment, buyProducts });
};
processOrder();
}, [payment, buyProducts, mutateAddOrder]);
참고
https://ko.react.dev/learn/lifecycle-of-reactive-effects
https://velog.io/@summereuna/리액트-useEffect-무한-루프-탈출하기