javascript - 如何增加/减少购物车中产品的数量?

标签 javascript reactjs axios sequelize.js

我在实现从购物车中添加或删除产品的逻辑时遇到了一些困难。
首先在我的数据库级别:

  • 每个购物篮包括:购物篮 ID、产品 ID、客户 ID 和数量。

  • 这意味着用户实际上有“几个篮子”(一个产品=一个篮子)
    后端
    以下是我如何使用 sequelize 创建模型/关系:

    // Inside db.config.js 
    db.paniers = sequelize.define('panier', {
       id: {
          type: Sequelize.INTEGER,
          primaryKey: true,
          autoIncrement: true,
          field: 'PAN_ID'
      },
       userId: {
          type: Sequelize.INTEGER,
          references: {
             model: db.users,
             key: 'USE_ID'
          },
          primaryKey: true,
          allowNull: false,
          field: 'USE_ID'
       },
       produitId : {
          type: Sequelize.INTEGER,
          references: {
             model: db.produits,
             key: 'PRO_ID'
          },
          primaryKey: true,
          allowNull: false,
          field: 'PRO_ID'
       },
       quantite: {
          type: Sequelize.INTEGER,
          allowNull: false,
          field: 'PAN_QUANTITE'
       }
    }, {
       tableName: 'PANIER'
    });

    然后对于查询,进行两个查询:
  • 一个显示有关购物车的信息(购物车 ID、产品 ID、产品名称、产品价格、产品图片、购物车数量)
  • 另一个更新数量。

  • 这是我在 POSTMAN 下进行 axios 查询和结果的方式

    const APIURL = 'http://localhost:8090/api';
    
    // Get the details of the cart
    export const getDetails = (userId) => axios.get(`${APIURL}/panier/details/${userId}`,
    {
        userId: userId,
    });
    
    // Update the quantity of the cart
    export const updateQuantite = (produitId) => axios.put(`${APIURL}/panier/${produitId}`, 
    {
        produitId: produitId,
    });



        // Result for the userId 1 (getDetails)
        {
            "PRO_ID": 1,
            "PRO_NOM": "Un immeuble",
            "PRO_PRIX": "1515",
            "PRO_URL": "58afa4f2-41b1-42f7-a371-6d267784c44e.jpg",
            "PAN_QUANTITE": 1,
            "PAN_ID": 1
        },
        {
            "PRO_ID": 2,
            "PRO_NOM": "Model",
            "PRO_PRIX": "102",
            "PRO_URL": "a76fbe76-a183-49fa-84ee-40d5da08b91f.png",
            "PAN_QUANTITE": 1,
            "PAN_ID": 2
        }
        
        

    这是我的两个 Controller 管理他的路线:

    // Display the informations of the basket
    exports.getDetails = (req, res) => {
        const queryResult = db.sequelize.query(
          'SELECT P.PRO_ID, PRO_NOM, PRO_PRIX, PRO_URL, PA.PAN_QUANTITE, PA.PAN_ID\n' +
          'FROM panier AS PA INNER JOIN produit AS P ON PA.PRO_ID = P.PRO_ID\n' +
          'WHERE USE_ID = :id',
          {
            replacements: { id: req.params.userId },
            type: QueryTypes.SELECT
          }
        ).then(panier => {
            res.json(panier);
        }).catch(err => res.status(400).send(err));
    }
    
    // Modify the quantity of a basket
    exports.update = (req, res) => {
        Paniers.update({
            quantite: req.body.quantite
        }, {
            where: {
                produitId: req.params.produitId
            }
        }).then(panier => {
            res.json(panier);
        }).catch(err => res.status(400).send(err));
    }

    前端
    这就是我的信息的显示方式(仍在开发中,这就是为什么它看起来不像任何东西^^')
    Display 2 baskets for a user, with 2 buttons : plus and minus
    这就是我迷路的地方...
    这是我的购物车 pagePage.js :

    import React, { useState, useEffect } from 'react';
    import { Card, CardHeader, CardMedia, Grid, ButtonGroup, Button} from '@material-ui/core';
    import PayPal from '../services/PayPal/paypal'
    import {getDetails, updateQuantite, getAllPanier, get} from '../services/API/panier'
    
    
    export default function PanierPage() {
    
    
            // Récupération des détails des paniers
            const [paniers, setPaniers] = useState([])
            const getPaniersDetails = () => [
                getDetails(JSON.parse(localStorage.getItem('User')).id).then(response => {
                    setPaniers(response.data)
                    console.log(response)
                }).catch(err => console.log(err))
            ]
    
            const handleIncrement = (id) => {
                    updateQuantite(id).then(response => {
                        // ???
                }).catch(err => console.log(err))
            }
            
            const handleDecrement = () => {
            }
    
    
            // Affichage des détails des paniers 
            const paniersAffichage = paniers.map((panier) => (
                <Grid container>
                    <Card key={panier.PAN_ID}>
                        <CardHeader title={panier.PRO_NOM}/>
                        <CardMedia image={`http://localhost:8090/${panier.PRO_URL}`}/>
                            <Button onClick={() => handleIncrement(panier.PRO_ID)}> + </Button>
                                {panier.PAN_QUANTITE}
                            <Button onClick={handleDecrement}> - </Button>
                    </Card>
                </Grid>
            ));
    
    
            // Chargement des produits
            useEffect(() => {
                getPaniersDetails();
            }, [])
    
        return (
                <>
                    <Grid>
                        {paniersAffichage}
                    </Grid>
                    <PayPal/>
                </>
            );
    }

    解释:
  • 我在“getPaniersDetails”中获取我的购物篮信息,我在其中指出用户 ID,然后将其加载到我的 useEffect 中。
  • basketsDisplay 允许我显示相关用户的购物篮。
  • 我在每张卡片中为映射提供购物车的 ID,然后显示信息......
    点击“+”时,我想增加我的数量,所以我给它产品 ID。
  • 因此,handleIncrement 将使用“updateQuantite”处理此操作。
  • 这就是我阻止的地方,我觉得自己在不同的 ID 之间混在一起。特别是在表的购物车 ID 和我的查询(SELECT)的购物车 ID 之间

  • 我敢肯定,设置起来非常简单,但在我看来,这对我来说似乎很复杂......
    如果我错过了任何重要的点告诉我,我会尽力改变我的帖子

    最佳答案

    您的对象模型没有多大意义。
    我会改变它以使其更具活力。
    如果您有用户,并且他们有一个购物篮属性,那么这种方法更有意义。
    注意:下面的代码是一个粗略的大纲,但应该让您知道如何去做。

    interface Database {
        users: User[]; // Array of users.
    }
    
    interface User {
        id: number;
        username: string;
        passwordHash: string;
        baskets: Basket[];
    }
    
    interface Basket {
        id: number;
        items: Item[]; // array of items;
        date: string;
    }
    
    interface Item {
        id: number; // ID of the item.
        name: string;
        imgURL: string;
        description: string[];
        quantity: number;
    }
    
    现在,如果我们想要接收数据并将数据发送到数据库,我们会这样做。
    interface Basket {
        items: string[]; // list of item id's.
    }
    
    // You want to use a session token instead of the user id so noone but the user can access their basket. 
    // Normaly baskets will be local to the browser or app and not sored on a servers database. 
    // Only past orders should be stored. But in this example, we are storing the current basket too.
    async function getBasket(sessionToken: string){
        return await axios.get(`${api.host}/basket`, { 
            headers: {
                Session-Token: sessionToken, // used to identify the user
                Content-Type: "application/json",
            }
        }).data;
    }
    
    // we send the basket object, which is just a list of IDs, and the session token.
    async function setBasket(basket: Basket, sessionToken: string){
        return await axios.put(`${api.host}/basket`, { 
            headers: {
                Session-Token: sessionToken, // used to identify the user
                Content-Type: "application/json",
            }
        }).data;
    }
    
    现在在服务器端,我们可以使用 express 处理请求。
    要使用 express 实现 session ,有 npm 模块 express-session这是 express 的中间件。当用户登录时,他们将获得一个标题,他们将保存为 cookie 以用于他们 future 的请求。当他们注销时, session 将从您的服务器中删除,并且 cookie 在客户端上被删除。
    为了增加安全性,您可以设置 session 的过期时间。用户将不得不重新登录并获得一个新 session 。
    
    // check the documentation to tune it to what you need.
    app.use(session({
      secret: 'mySuperSecret',
      resave: false,
      saveUninitialized: true,
      cookie: { secure: true }
    }))
    
    app.get("/basket", async(req, res) => {
        // here we first check if the session exists.
        if(req.session.views){
            // if it does, then we return the list of baskets.
            const { baskets } = await getUser(req.session.userID);
            res.sendStatus(200).send([success: true, data: baskets]);
        }
        // if not, then we will return a 403 error.
        // we also send a response that matches the layout of the normal response.
        res.sendStatus(403).send([success: false, data: []]);
        
    })
    
    app.put("/basket", (req, res) => {
        // here we first check if the session exists.
        if(req.session.views){
            // if it does, then we add the basket to the user.
            addBasket(req.session.userID, basket)
                .then(res.sendStatus(204).send([success: true, data: []]))
        }
        // if not, then we will return a 403 error.
        // we also send a response that matches the layout of the normal response.
        res.sendStatus(403).send([success: false, data: []]);
    })
    
    如果您有任何问题,请在评论部分提出。我有空时会回复。

    关于javascript - 如何增加/减少购物车中产品的数量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67622765/

    相关文章:

    javascript - 如何在javascript中获取给定类型的所有对象

    javascript计算数组中的重复项

    javascript - React 如何跳转到表单中的目标输入区域?

    Node : POST - Request Method: OPTIONS Status Code: 403 Forbidden

    javascript - 在 JavaScript 中从服务器导出 Excel 表格

    javascript - Node.js:socket.io 关闭客户端连接

    Javascript 预加载回调

    javascript - Actions 必须是 React/Redux 中的普通对象吗?

    reactjs - 使用 ES6 在 React 组件中定义方法的语法是什么

    javascript - React 组件中的 children Prop