본문 바로가기

CodeTech/React

React - [깊은 복사 얕은 복사, 상태변수와 반환형 함수]

투레벨 프로젝트를 진행하고 있다.

그런데 문제가 생겨서 아무리 생각해도 이유를 찾지 못해서 다른 문제들 부터 해결하고 다시 도전해봤다.

 

문제

const removeToCart = (title) => {
        if (cart.length === 1) {
            setCart([]);
            window.localStorage.removeItem('cart');
            return
        }
        setCart(cart.filter(product => product.title !== title));
        console.log(cart);
        window.localStorage.setItem('cart', JSON.stringify(cart));
    }

페이지를 만들고 있는데 오른쪽의 장바구니 페이지에서 상품 remove 버튼을 누르면 AddToCart컴포넌트로 넘어가서 

위와 같이 reduceProduct가 시작으로 동작하는 원리인데 이렇게 하면 상품이 지워지긴 지워지는데 지워진후 다시 다른 상품을 추가하면 cart에서 지워지지 않은 기록으로 장바구니에서 마치 지워지지 않았던 문제가 생겼다.

 

filter 함수를 써서 상품 타이틀을 가진 객체만 제외하고 다른 상품들을 넣어서 마치 해당 상품만 없어진것 처럼 장바구니 remove를 하였는데 filter 함수가 문제일줄은 몰랐다. 더군다나 cart.filter함수를 사용하면 cart는 useState 변수이기 때문에 변경되지 않은 cart값을 넘겨준다는 것이다. 

 

해결

보통 소거법으로 문제의 해결원인을 찾아나가지만 이경우에는 설마 filter 함수가 문제일줄은 몰랏기에 window.localStorage에 저장되는 cart 값과 setCart가 실행될떄 JS는 동기식으로 코드가 실행되기때문에 실행순서가 꼬여서 문제가 일어난줄 알았다.

 

굉장히 많은 구글링과 비동기식 코드 처리를 했음에도 문제가 해결되지 않자 이문제는 아니라고 가정하고 filter 방법대신 splice로 해당 상품을 제거 하는 다른 방법을 사용했다.

const removeToCart = (index) => {
        if (cart.length === 1) {
            setCart([]);
            window.localStorage.removeItem('cart');
            return
        }
        var newCart = JSON.parse(JSON.stringify(cart));
        newCart.splice(index, 1)
        setCart(newCart);
        window.localStorage.setItem('cart', JSON.stringify(newCart));
        console.log(cart);
    }

var newCart 변수를 사용해서 cart값을 깊은 복사를 통해 저장한다.

 

(자바스크립트에서 객체 복사를 할때는 깊은 복사를 해야한다. 객체는 참조 변수이기 때문이다. 깊은 복사를 위한 방법으로서 JSON.parse(JSON.stringify())를 사용했다.)

 

splice 함수를 사용하자 바로 해결되었다..

 

filter 함수는 다음부터는 useState 변수와 같이 사용하면 깊은 복사를 하고 진행하거나

다른 반환형 함수를 사용할때 상태변수를 같이 사용하는 일이 없도록 해야겠다.