如何将数据从Redux上传到数据库?

7hiiyaii  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(118)

我有一个React前端和Laravel后端与MySql数据库的项目。我试图通过构建这个项目来学习React和Laravel。
如果用户还没有登录,我正在尝试将产品放入Redux。用户登录后,我试图将产品从Redux移动到数据库中的购物车表,包括user_id。如果用户在将产品添加到Redux之前登录,我会尝试将产品直接保存到数据库的购物车表中。有人能帮我写代码吗?
amazonSlice.js

import React, { useEffect, useState } from 'react'
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";

const initialState = {
  products: [],
  userInfo:[],
  status: 'idle'
};

export const updateCartOnSignIn = createAsyncThunk('amazon/updateCartOnSignIn', async (selectItems, { getState }) => {

    const [apitoken, setapitoken] = useState('');
    useEffect(() => {
        const storedapitoken = localStorage.getItem('api_token');
        if (storedapitoken) {
            setapitoken(storedapitoken);
        }
    }, []);

    const { userInfo } = getState().amazon;
    try {
      const response = await axios.post('http://127.0.0.1:8000/api/user/updatecart',{user_id: userInfo.id, selectItems}, {
          headers: {
            Authorization: `Bearer ${apitoken}`, 
          },
      });
      return response.data;
    } catch (error) {
      throw error;
    }
}
);

export const amazonSlice = createSlice({
  name: "amazon",
  initialState,
  reducers: {
    // Actions
    addToCart: (state, action) => {
      const item = state.products.find((item) => item.id === action.payload.id)
      if(item) {
        item.quantity += action.payload.quantity
      } else { 
        state.products.push(action.payload)
      }
      
    },

    removeFromCart: (state, action) => {
      state.products = state.products.filter((item) => item.id !== action.payload)
    },

    clearCart: (state) => {
      state.products = []
      window.scrollTo({ top: 0 });
    },

    quantityIncrement: (state,action) => {
      const item = state.products.find((item) => item.id === action.payload)
      item.quantity++
    },

    quantityDecrement: (state, action) => {
      const item = state.products.find((item) => item.id === action.payload)
      if(item.quantity === 1) {
        item.quantity = 1
      } else {
        item.quantity --
      }
    }
  },
});

export const { addToCart, removeFromCart, clearCart, quantityIncrement, quantityDecrement } = amazonSlice.actions;

// Selectors - This is how we pull information from the Global store slice
export const selectItems = (state) => state.amazon.products;
export const selectTotal = (state) => state.amazon.products.reduce((total, item) => total + (item.price * item.quantity) , 0)

export default amazonSlice.reducer;

Product.js

import Image from 'next/legacy/image'
import React, { useEffect, useState } from 'react'
import { StarIcon } from '@heroicons/react/24/solid'
import Currency from 'react-currency-formatter';
import prime from '../../images/prime.png'
import axios from 'axios';

import { useDispatch, useSelector } from 'react-redux';
import { addToCart, updateCartOnSignIn, selectItems, clearCart } from '@/slices/amazonSlice';

const Product = ({ id, title, price, description, category, src }) => {

    const dispatch = useDispatch()

    const itemsInCart = useSelector(selectItems);

    const [apitoken, setapitoken] = useState('');
    const [userid, setuserid] = useState('');
    useEffect(() => {
        const storedUsername = localStorage.getItem('api_token');
        const storedUserid = localStorage.getItem('userid');
        if (storedUsername && storedUserid) {
            setapitoken(storedUsername);
            setuserid(storedUserid);
        }
    }, []);

    async function clickAddToCart(e) {
        const isAuthenticated = !!apitoken;

        if(!isAuthenticated) {
            dispatch(addToCart({
                id,
                title,
                description,
                price,
                category,
                src,
                quantity: 1,
            }))
            
        } 
        else if(isAuthenticated && itemsInCart.length > 0 ) {
            try {
                    dispatch(updateCartOnSignIn);
                    dispatch(clearCart());
            } catch (error) {
                alert(error);
            }
        } 
            else {
            let response = await axios.post('http://127.0.0.1:8000/api/user/updatecart', {id, title, price, description, category, src, quantity:1}, {
                headers: {
                    Authorization: `Bearer ${apitoken}`
                }
            })
            if(response) {
                console.log(response)   
            }

            dispatch(addToCart({
                id,
                title,
                description,
                price,
                category,
                src,
                quantity: 1,
            }))    

        }
    }

    return (
        <div className='relative flex flex-col m-5 bg-white z-30 p-10'>
            <p className='absolute -top-2 right-2 text-xs italic text-gray-400 my-3'>{category}</p>

            <img src={src} width={200} height={200} style={{ objectFit: 'contain', paddingBottom: '13px' }} alt="img" />

            <h4>{title}</h4>

            <p className='text-sm my-2 line-clamp-2'>{description}</p>

            <div className='mb-5'>
                {/* currency is USD by default */}
                <Currency quantity={price} /> 
            </div>

            <button onClick={clickAddToCart} className='mt-auto button'>Add to Basket</button>

        </div>
  )
}

export default Product

api.php

Route::middleware('auth:sanctum')->post('/user/updatecart', [ProductController::class, 'updatecart']);

ProductController.php

public function updateCart(Request $request) {
    if (Auth::check()) {
        $user_id = Auth::id();

        $existingCartItem = Cart::where('user_id', $user_id)
            ->where('product_id', $request->id)
            ->first();

        if ($existingCartItem) {
            $existingCartItem->quantity += $request->quantity;
            $existingCartItem->save();
        } else {
            $cart = new Cart();
            $cart->user_id = $user_id;
            $cart->product_id = $request->id;
            $cart->quantity = $request->quantity;
            $cart->save();
        }

        return response()->json(['message' => 'Cart updated successfully']);
    } else {
        return response()->json(['message' => 'User not authenticated'], 401);
    }
}

购物车迁移文件

public function up()
{
    Schema::create('carts', function (Blueprint $table) {
        $table->id();
        $table->string('user_id');
        $table->string('product_id');
        $table->string('quantity');
        $table->timestamps();
    });
}
qvk1mo1f

qvk1mo1f1#

在您的Product component中,您正在正确地分派操作以在Redux中将项目添加到购物车。但是,当用户通过身份验证时,您可以分派updateCartOnSignIn操作,但不向其传递任何数据。您应该将itemsInCart数组作为参数传递给此操作,以便将其发送到服务器。
以下是如何在Product component中更新clickAddToCart函数:

async function clickAddToCart(e) {
    const isAuthenticated = !!apitoken;
    const cartItems = itemsInCart.map(item => ({
        id: item.id,
        title: item.title,
        description: item.description,
        price: item.price,
        category: item.category,
        src: item.src,
        quantity: item.quantity,
    }));

    if (!isAuthenticated) {
        dispatch(addToCart({
            id,
            title,
            description,
            price,
            category,
            src,
            quantity: 1,
        }));
    } else if (isAuthenticated && itemsInCart.length > 0) {
        try {
            dispatch(updateCartOnSignIn(cartItems)); // Pass cartItems to the action
            dispatch(clearCart());
        } catch (error) {
            alert(error);
        }
    } else {
        try {
            const response = await axios.post('http://127.0.0.1:8000/api/user/updatecart', cartItems, {
                headers: {
                    Authorization: `Bearer ${apitoken}`,
                }
            });

            if (response) {
                console.log(response);
            }
        } catch (error) {
            alert(error);
        }

        dispatch(addToCart({
            id,
            title,
            description,
            price,
            category,
            src,
            quantity: 1,
        }));
    }
}

相关问题