• 로그인
  • 장바구니에 상품이 없습니다.

home2 게시판 Node.js, Express 게시판 react 장바구니 state 를 mongodb에 axios로 post, put 요청

react 장바구니 state 를 mongodb에 axios로 post, put 요청

10 글 보임 - 1 에서 10 까지 (총 10 중에서)
  • 글쓴이
  • #45078

    김지우
    참가자
    답변으로 항상 큰 도움 주셔서 감사합니다.
    다름이 아니라 오늘도 선생님께 질문이 있어서 찾아왔습니다.
    
    장바구니 기능에서 redux toolkit으로 관리중인 state.cart 를 db로 한번 저장해보려고 합니다.
    그래서 cartState 라는 collection 하나 만들었고
    server.js 에서는 우선 이렇게 코드를 추가했습니다.
    
    app.post('/cart', function(요청, 응답){
     응답.send('전송완료');
     db.collection('cartState').insertOne(state.cart, function(){
     console.log('저장완료')
     });
    });
    app.put('/cart', function(요청, 응답){
     db.collection('cartState').updateOne(state.cart, function(){
     console.log('수정완료')
     응답.redirect('/cart')
     });
    });
    
    그리고 Detail.js 에서 버튼을 누르면 axios 로 state.cart 를 이렇게 post 요청하고
    
    <button
    className = "buttonGreen"
    style={{width:'85px'}}
    onClick={() => {
    찾은상품개수변경(()=>{
     찾은상품.quan --;
     })
    dispatch(
    addItem({ id: 찾은상품.id, name: 찾은상품.title, quan: 1})
     );
    navigate("/cart");
     axios.post("/cart").then((결과) => console.log(결과)).catch(() => console.log("전송 실패!"))
     }}
    >
     장바구니
     </button>
    
    Cart.js 에서 +1, -1 버튼을 누르면 axios 로 state.cart 를 이렇게 put 요청했습니다
    
    <button className="buttonOrange" role="button" onClick={
     ()=>{dispatch(addCount(a.id))
     axios.put("/cart").then((결과) => console.log(결과)).catch(() => console.log("전송 실패!"))}}>
     +1</button>
     <button className="buttonGreen" role="button" onClick={
     ()=>{dispatch(subCount(a.id))
     axios.put("/cart").then((결과) => console.log(결과)).catch(() => console.log("전송 실패!"))}}>
     -1</button>
    
    그런데 여기서 아래처럼 에러가 발생합니다
    detail.js 의 장바구니 추가버튼은 브라우저 콘솔에서 전송완료라고 뜨는데, (다시 확인해보니 cartState collection 에 추가되지 않고 아예 비어있네요)
    cart.js 의 +1, -1 버튼은 콘솔에서 전송 실패가 뜹니다 (콘솔 사진 첨부했습니다). 그리고 vsc 터미널에서는 아래와 같은 에러가 뜹니다. state 가 정의되지 않았다는 게 무슨 말일까요? 
    server.js 까지 state가 전달 되지 않는 것 같은데 
    state 를 어떻게 전달해야 할지 잘 이해가 가지 않습니다ㅠㅠ (애초에 그럼 detail.js 의 장바구니 버튼은 왜 전송완료라고 뜨는걸까요?)
    
    ReferenceError: state is not defined
        at /Users/ziuss/Documents/GitHub/hochony1/server.js:66:40
        at Layer.handle [as handle_request] (/Users/ziuss/Documents/GitHub/hochony1/node_modules/express/lib/router/layer.js:95:5)
        at next (/Users/ziuss/Documents/GitHub/hochony1/node_modules/express/lib/router/route.js:144:13)
        at Route.dispatch (/Users/ziuss/Documents/GitHub/hochony1/node_modules/express/lib/router/route.js:114:3)
        at Layer.handle [as handle_request] (/Users/ziuss/Documents/GitHub/hochony1/node_modules/express/lib/router/layer.js:95:5)
        at /Users/ziuss/Documents/GitHub/hochony1/node_modules/express/lib/router/index.js:284:15
        at Function.process_params (/Users/ziuss/Documents/GitHub/hochony1/node_modules/express/lib/router/index.js:346:12)
        at next (/Users/ziuss/Documents/GitHub/hochony1/node_modules/express/lib/router/index.js:280:10)
        at serveStatic (/Users/ziuss/Documents/GitHub/hochony1/node_modules/serve-static/index.js:75:16)
        at Layer.handle [as handle_request] (/Users/ziuss/Documents/GitHub/hochony1/node_modules/express/lib/router/layer.js:95:5)
    
    
    #45134

    codingapple
    키 마스터
    post요청으로 서버에 데이터를 보내야 서버는 데이터수신이 가능합니다
    axios.post('/경로', 보낼데이터) 이럽시다
    그럼 서버에선 요청.body.어쩌구 하면 데이터 나옵니다
    #45185

    김지우
    참가자
    아아 그런것이었군요. 그래서 아래처럼 post 요청을 했습니다.
    axios.post("/cart", state.cart).then((결과) => console.log(결과)).catch(() => console.log("전송 실패!"))
    
    put 요청도 똑같을 것 같아서 아래처럼 보낼 데이터를 넣었습니다.
    <button className="buttonOrange" role="button" onClick={
     ()=>{dispatch(addCount(a.id))
     axios.put("/cart", state.cart).then((결과) => console.log(결과)).catch(() => console.log("전송 실패!"))}}>
     +1</button>
    
    그런데 server.js 가 잘 감이 오질 않아서 여러 시도를 해봤습니다.
    
    app.post('/cart', function(요청, 응답){
     응답.send('전송완료');
     db.collection('cartState').insertOne(요청.body.state.cart, function(){
     console.log('저장완료')
     });
    });
    app.put('/cart', function(요청, 응답){
     db.collection('cartState').updateOne(요청.body.state.cart, function(){
     console.log('수정완료')
     응답.redirect('/cart')
     });
    });
    
    저 위에 요청.body.state.cart 를 넣은 부분에 그냥 state.cart 를 넣으면 state 가 정의되지 않았다고 떠서 이렇게 넣은 것인데
    TypeError: Cannot read properties of undefined (reading 'cart')
    이런 에러가 뜹니다.
    
    그리고 state.cart 초기값이 원래 빈 배열이니 요청.body.state.cart[0] 이렇게 넣어야 하는 건가 싶었는데도 에러가 뜨더군요
    state.cart 가 여기서 요청.body 인 것인가 싶어 요청.body 나 요청.body[0] 도 마찬가지 입니다. must be valid Javascript Object 이런 에러가 뜹니다.
    
    여기에 무엇을 넣어야 하는 걸까요?
    애초에 제가 state.cart 를 잘못 넣은 것일까요?
    #45216

    codingapple
    키 마스터
    리액트에서 state.cart부터 출력해보고 잘 있으면 서버에서 요청.body도 똑같이 나오나 출력해봅시다
    #45471

    김지우
    참가자
    app.post('/cart', function(요청, 응답){
     응답.send('전송완료');
     db.collection('cartState').insertOne(요청.body, function(){
     console.log(요청.body);
     console.log('저장완료');
     });
    });
    app.put('/cart', function(요청, 응답){
     응답.send('전송완료');
     db.collection('cartState').updateOne(요청.body, function(){
     console.log(요청.body);
     console.log('수정완료');
     });
    });
    
    제가 put 요청에 응답.send() 를 안해줘서 오류가 난 것 같습니다.
    이제 브라우저 콘솔에서도 {data: "전송완료", status: 200, statusText: "OK", headers: Object, config: Object, …} 이런게 post, put 요청 할 때 모두 잘 뜨네요.
    react 에서도 state.cart 가 잘 뜹니다. 하지만 문제는 post 요청을 할 때 state의 초기값인 [] 가 전송된다는 게 문제인 것 같습니다.
    (리액트에선 장바구니 화면에 추가되면 빈 어레이를 뱉고 + 를 누르면 그제서야
     Array (1)
    0 {_id: 0, id: 0, name: "This is my seat", quan: 1}  이렇게 1개로 콘솔에 띄워줍니다.
    
    아래는 빈 어레이가 뜨는 detail.js
    
    axios.post("/cart", state.cart).then((결과) => console.log(결과)).catch(() => console.log(state.cart))
    
    이건 quan: 1개씩 늦게 뜨는 cart.js 코드입니다.
    
    <button className="buttonOrange" role="button" onClick={
     ()=>{dispatch(addCount(a.id))
     axios.put("/cart", state.cart).then((결과) => console.log(결과)).catch(() => console.log(state.cart))}}>
     +1</button> ) 
    
    그래서 아래처럼 서버에서는 새 _id 를 붙여주긴 하지만 빈 어레이다 보니 collection 에 저장을 해주진 않네요. 실제로 몽고디비 가보면 컬렉션이 비어있습니다.
    
    [ _id: new ObjectId("6315f4034e0e2c4f608107af") ]
    저장완료
    
    그리고 아래 이 에러는 put요청을 할때, 즉 + 버튼을 누를 때 일어납니다.
    MongoInvalidArgumentError: Document must be a valid JavaScript object
    
    
    #45485

    codingapple
    키 마스터
    dispatch 완료되기 전에 ajax요청되어서 그런가봅니다 
    addCount 함수 안에서 state변경 후 ajax 요청해봅시다 
    
    #45535

    김지우
    참가자
    말씀하신대로 아래와 같이 store.js 에서 함수 안에서 state 변경 후 ajax 요청을 해봤습니다.
    그랬더니 post 요청은 새로운 _id 를 배정해서 collection에 추가를 해 주지만 아직도 빈 어레이를 넣는 것 같습니다.
    그리고 여전히 put 요청은 MongoInvalidArgumentError: Document must be a valid JavaScript object 에러를 띄웁니다.
    제가 ajax 요청을 잘못 하고 있는 것일까요??
    
    let cart = createSlice({ // state 생성 + useState 같은 거임, state + reducer 를 slice 라고 부름
    name : 'cart', // 함수 형태의 reducer 라 깔끔하고 원래 복사본 만드는 걸 자동으로 해줘서 원본 바꾸는 형태로 사용 가능
    initialState : [],
    reducers : {
    // 변수로 초기값 만들고 reducer 안에 넣기 그리고 state 수정하는 법도 작성
    addItem(state, action) {
    let found = state.findIndex((a)=>{return a.id === action.payload})
    if (found >= 0){
     state[found].quan++;
     } else {
     state.push(action.payload);
     }
     axios.post("/cart", state.cart).then((결과) => console.log(결과)).catch(() => console.log(state.cart));
     },
    addCount (state, action) {
    let found = state.findIndex((a)=>{return a.id === action.payload})
     state[found].quan++;
     axios.put("/cart", state.cart).then((결과) => console.log(결과)).catch(() => console.log(state.cart));
     },
    subCount(state, action) {
    let found = state.findIndex((a)=>{return a.id === action.payload})
    if (state[found].quan > 1) {
     state[found].quan--;
     } else if (state[found].quan <= 1) {
    delete(state[found]);
     }
     axios.put("/cart", state.cart).then((결과) => console.log(결과)).catch(() => console.log(state.cart));
     }
     }
    });
    
    
    #45578

    codingapple
    키 마스터
     state.push(action.payload); 하는거 보니까 state는 array자료같은데
     axios.post("/cart", state.cart 에선 state를 object처럼 쓰고있군요
    #45604

    김지우
    참가자
    바보같이 복붙해버렸네요...ㅠㅠ 선생님 말씀대로 state는 array 자료가 맞습니다.
    axios.post("/cart", state 로 바꾸고,
    서버에서는 db.collection('cartState').insertMany(요청.body, function(){
    이렇게 하니 잘 옮겨 집니다. 
    그런데 문제점은 뒤로가기를 눌러서 다른 품목 하나를 더 추가해서 state를 [{제품 1번의 정보}, {제품 2번의 정보}] 이렇게 만들어도
    collection은 최초 제품 1개 밖에 업로드 하지 않네요.. 아마 이미 제품 1번이 이미 있어서 1번과 2번을 한꺼번에 넣는 것은 중복이라 안되는 것 같습니다.
    제품 1번이 있으면 다시 장바구니에 넣어도 안되듯이 말입니다.
    
    그리고 제가 updateOne 도 전혀 잘못 이해하고 있었습니다.
    state 전체를 모두 한번에 쉽게 업데이트 할 수 있을 것 같았는데 MongoDB 메뉴얼을 보고서 
    이걸로 장바구니 state 를 수정하는 게 매우 복잡할 것 같다는 생각이 들었습니다.
    다시 한번 고민해보고 너무 불필요한 코드가 많아질 것 같다면 다시 localStorage 를 활용하는 방법으로 가보겠습니다!
    이번에도 친절한 답변 감사합니다 선생님!
    
    
    #45641

    codingapple
    키 마스터
    버튼누를 때 마다 state를 꺼내서 전부집어넣는게 아니라 추가되는 상품만 집어넣어도 됩니다
10 글 보임 - 1 에서 10 까지 (총 10 중에서)
  • 답변은 로그인 후 가능합니다.

About

현재 월 700명 신규수강중입니다.

  (09:00~20:00) 빠른 상담은 카톡 플러스친구 코딩애플 (링크)
  admin@codingapple.com
  이용약관, 개인정보처리방침
ⓒ Codingapple, 강의 예제, 영상 복제 금지
top

© Codingapple, All rights reserved. 슈퍼로켓 에듀케이션 / 서울특별시 강동구 고덕로 19길 30 / 사업자등록번호 : 212-26-14752 온라인 교육학원업 / 통신판매업신고번호 : 제 2017-서울강동-0002 호 / 개인정보관리자 : 박종흠