Developer/PROJECT.React

리액트 프로젝트 7. 구매 유저 정보 입력 , 구매 완료까지

단님 2024. 7. 2. 16:10
728x90
ProductBuy-BuyInputBox

 

구매하기를 누르면 진행되는 배송지 위치 , 이름 , 연락처 정보를 받아야한다.

물론 유저데이터에 저장해 놓은 값을 쓸수도 있지만

보통은 새로운 배송지 입력이 가능하도록 하는 기능들이 있는것을 보았다.

 

내 구현목표는

1. 새로운 배송지를 입력할 수 있게 만들것.

2. 현재 배송지도 값을 변경할 수 있도록 할것.

3. 배송 메세지를 직접입력 가능하도록 할것.

4. 입력 유효를 확인하여 구매하기 버튼 활성화를 할 것.

 

form의 기능을 제대로 써야하지만 ,

우리는 미리 만들어 놓은 데이터를 import 하거나 세션에 올려놓은 정보들로 찾고 있기 때문에 

제대로 된 form 의 기능을 쓰지 못했다.

 

유저정보의 데이터는 나중에 정보 업데이트에 이용해야겠지만 , 

현재로는 값을 저장하는데 그쳤다.

 

유저 관리를 위한 저장 변수를 state로 선언하고

첫 userDate가 있을때, 그 유저정보들을 각 위치에 맞게 넣어주었고,

 

새로운 배송지를 누르게 되면 빈 문자열로 만드는 작업을 하였다.

 

  //배송지 선택에 따라 input값을 변환.
    const onChangeAddressing = () => {
        if (addressing) {
            setUserInfo({
                name: '',
                ...
                ...
            });
        } else {
            setUserInfo({
                name: userData.name || '',
                ...
                ...
            });
        }
        setAddressing(!addressing);
    };

 

수기로 작성했을때는 그 값들이 들어 갈 수있도록 넣어주었다.

    const onChangeUserInfo = (e) => {
        const { name, value } = e.target;
        setUserInfo((info) => ({
            ...info,
            [name]: value,
        }));
    };

 

우편번호를 이용하는 방법은 카카오 api 우편번호를 이용하였는데

로그인 회원가입을 담당하는 친구가 해놓은 것을 가지고 와서 이용하였다.

 

리턴에는 이런식으로 이용하게 되었다.

<input
    type="radio"
    name='delivery'
    id='basicsAddress'
    checked={addressing}
    onChange={onChangeAddressing}
/>
<label htmlFor="basicsAddress">기본 배송지</label>
<input
    type="radio"
    name='delivery'
    id='newAddress'
    checked={!addressing}
    onChange={onChangeAddressing}
/>
<label htmlFor="newAddress">새로운 배송지</label>
<input
    type="text"
    id='name'
    name="name"
    value={userInfo.name}
    onChange={onChangeUserInfo}
/>
<label htmlFor="phoneNumber">연락처</label>

수기로 입력하던 , 불러오던 제대로 값이 들어가는것을 console.log를 통해 확인 할 수 있었다

 

 

배송 메세지를 직접 입력할경우 인풋창을 활성화 하는것은 state를 이용해서 활성화 하는것은 쉬웠지만,

직접입력 일경우 열고 , 아닌경우 닫게 했더니

입력과 동시에 사라지는 부분이 생겨서,

다른것을 선택했을때 사라지도록 사라지는 조건을 알맞게 지정해줬어야했다

select가 지정될때마다 제대로 된 값이 들어가는것을 확인해 볼수 있다.

직접입력했을때는 어떨까 ?

 

useEffect를 통해 selectBox를 직접 다시 변경해주었다.

    useEffect(()=>{
        if (selectBox.deliveryMessage === '직접입력' && !directInput) {
            setDirectInput(true);
            SetSelectBox(it => ({ ...it, deliveryMessage: '' }));
        }

    }, [selectBox.deliveryMessage, directInput]);

문제는 의존성 배열을 직접 실행하기때문에 두번 랜더링이 발생되는 부분이 생겨서

useEffect를 기존에 있던것과 합치지 않고 의존성 배열을 구체화 하여 최소화 하였다.

 

구매버튼 활성화는 어떤 방법을 통해서 할까 ? 생각했고,

빈배열이 발견된다면 , 그것을 배열로 집어넣을 수 만 있다면 길이 조사가 가능하지 않을까 해서

객체를 순회하는 메서드를 찾아봤다.


Object.values(obj): Object.values() 는 파라매터로 전달된 객체가 가지는 열거 가능한 속성의 값들로 구성된 배열을 반환합니다. 배열의 값들이 순서는 오브젝트의 속성을 for in 구문등으로 반복한 결과와 동일합니다. (참고로 for in 구문은 순서를 보장하지 않습니다)
var obj = {
	a: 2,
	b: 42,
	c: 4
};

Object.values(obj); // [2, 42, 4]

 

 

이 메서드를 활용해서 fiter해서 빈배열을 뽑아 내야겠구나 생각했고,

const checking = Object.values(userInfo).map(it => it.trim()).filter((it)=>it ==='');

 

checking의 길이가 0일것 이라는 조건을 하나 만들어 냈고,

 

상품들 중 하나라도 선택해야하는 조건을 달기위해

checkedCartItems의 길이를 조사해야겠다는 생각을 했다.

하지만 우린 본품도 필요하기 때문에

본품이 선택된다면 그 본품도 들어가는 하나의 새배열의 길이 조사를 하면서

그길이가 0 이상이여야 하는 조건을 만들어냈다.

 

그리고 구매방식을 체크하는 radio 버튼이 클릭이 되야지만 

즉 state 값이 들어와서 빈배열이 아닐경우에만 활성화시키는 

3가지 조건을 만족하면 구매버튼을 활성화 시키는 조건을 달아주었다.

if(checking.length ===0 && selectBox.buyHow !==''&& selectedALLproduct.length>0){
    setIsBuyButtonDisabled(false); //BUY 버튼 활성화
}else{
    setIsBuyButtonDisabled(true); // BUY 버튼 비활성화
}

 

 

구매버튼을 누르게 되는 이벤트로는

1. 구매한 사항들이 나오는 모달창을 띄울것.

2. 구매 기록을 세션스토리지에 남길것 

가데이터에 history라는 속성에 {date : 날짜형식 , item : [아이템의 아이디값]} 을 남기고 있었다

const history = { date: nowDay, item: selectedProduct ? [selectedProduct.id] : [] };

nowDay라는 변수안에는  현재 날짜를 만들어주는 new Date()를 이용하여 원하는 날짜 형식으로 만들어 놓고.

 

객체의 배열안에 장바구니에서 선택된 값을 push해주었다.

        checkedCartItems.map((item)=>{
            history.item.push(item.productId);
        });

 

이객체를 맨 앞에 놔줘야 할것같아서 카피한 유저데이터에 history 배열에 맨앞에 자리할 수 있도록 unshift 해주었다.

copyUserData.mypage.history.unshift(history);

 

그리고 나서 이 카피데이터를 세션스토리지에 set 해주었다.

sessionStorage.setItem('LoginUserInfo',JSON.stringify(copyUserData));

 

그리고 모달창이 오픈되고 구매이력을 확인할 수 있는 페이지로 이동할 수 있도록 링크를 걸어두었다.