在 React + Redux 中实现添加到购物车导致错误,无法获取添加的产品
Implementing add to cart in React + Redux results in error, cannot fetch added products
所以,我正在尝试将产品添加到购物车,这是一个对象,由 url 参数中传递的数量指定。它看起来像这样:
http://localhost:3000/cart/622d6150a1d5f82535d4b66c?qty=3
我设法使用 useLocation 拆分了数量 (qty) 参数,但我无法以某种方式控制台记录包含已添加到购物车的产品的 cartItems。
import React, {useEffect} from 'react'
import {useDispatch, useSelector} from 'react-redux'
import {Link, useLocation, useNavigate, useParams, useSearchParams} from 'react-router-dom'
import {addToCart} from '../actions/cartActions'
export const CartScreen = () => {
const productId = useParams()
const history = useNavigate()
const useQty = useLocation()
const qty = useQty.search ? Number(useQty.search.split('=')[1]) : 1
console.log(qty)
const dispatch = useDispatch()
const cart = useSelector((state) => state.cart)
const {cartItems} = cart
console.log(cartItems)
useEffect(() =>{
if(productId){
dispatch(addToCart(productId, qty))
}
},[dispatch, productId, qty])
return (
<div>CartScreen</div>
)
}
export default CartScreen
控制台显示类似这样的内容,它显示 url 参数中的 3,但显示一个空数组,它应该显示我已添加到购物车的产品数组。还有,GET http://localhost:3000/api/products/[object%20Object] 404 (Not Found)
是什么意思?仅供参考,产品是从 localhost:5000/api/products 中的 mongodb 获取的,但通过 localhost:3000
获取代理
如果这有任何帮助,因为我也在使用 Redux,这是我的 addToCart 操作、redux 存储文件、购物车减速器。
import axios from "axios";
import { CART_ADD_ITEM } from "../constants/cartConstants";
export const addToCart = (id, qty) => async (dispatch, getState) => {
const {data} = await axios.get(`/api/products/${id}`)
dispatch({
type: CART_ADD_ITEM,
payload: {
product: data._id,
name: data.name,
image: data.image,
price: data.price,
countInStock: data.countInStock,
qty
}
})
localStorage.setItem('cartItems', JSON.stringify(getState().cart.cartItems))
}
import {createStore, combineReducers, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
import {composeWithDevTools} from 'redux-devtools-extension'
import { productListReducer, productDetailsReducer } from './reducers/productReducers'
import { cartReducer } from './reducers/cartReducers'
const reducer = combineReducers({
productList: productListReducer,
productDetails: productDetailsReducer,
cart: cartReducer,
})
const cartItemsFromLocalStorage = localStorage.getItem('cartItems') ? JSON.parse(localStorage.getItem('cartItems')) : []
const initialState = {
cart: {cartItems: cartItemsFromLocalStorage},
}
const middleware = [thunk]
const store = createStore(reducer,
initialState,
composeWithDevTools(applyMiddleware(...middleware)))
export default store
import {CART_ADD_ITEM} from "../constants/cartConstants"
export const cartReducer = (state = {cartItems: []}, action) => {
switch(action.type){
case CART_ADD_ITEM:
const item = action.payload
const existItem = state.cartItems.find(x => x.product === item.product)
if(existItem){
return{
...state,
cartItems: state.cartItems.map(x => x.product === existItem.product ? item : x),
}
} else {
return{
...state,
cartItems: [...state.cartItems, item]
}
}
default:
return state
}
}
您的 CartScreen
组件中只有一个小错误。您正在直接尝试使用 useParams
提取 productId
,但您不能这样做。因为 useParams
returns 一个 object
.
因此,如果您想使用 useParams
提取任何 dynamic value
。您必须 destructure
如下所示:
const { productId } = useParams()
这可以通过像这样重构 CartScreen.js 中的变量来解决:
const {productId} = useParams()
const useQty = useLocation()
const qty = useQty.search ? Number(useQty.search.split('=')[1]) : 1
为此:
const { id } = useParams();
const { search } = useLocation();
const productId = id;
const qty = search ? Number(search.split("=")[1]) : 1;
现在它在数组中显示产品详细信息,老实说我不知道这里发生了什么。
所以,我正在尝试将产品添加到购物车,这是一个对象,由 url 参数中传递的数量指定。它看起来像这样:
http://localhost:3000/cart/622d6150a1d5f82535d4b66c?qty=3
我设法使用 useLocation 拆分了数量 (qty) 参数,但我无法以某种方式控制台记录包含已添加到购物车的产品的 cartItems。
import React, {useEffect} from 'react'
import {useDispatch, useSelector} from 'react-redux'
import {Link, useLocation, useNavigate, useParams, useSearchParams} from 'react-router-dom'
import {addToCart} from '../actions/cartActions'
export const CartScreen = () => {
const productId = useParams()
const history = useNavigate()
const useQty = useLocation()
const qty = useQty.search ? Number(useQty.search.split('=')[1]) : 1
console.log(qty)
const dispatch = useDispatch()
const cart = useSelector((state) => state.cart)
const {cartItems} = cart
console.log(cartItems)
useEffect(() =>{
if(productId){
dispatch(addToCart(productId, qty))
}
},[dispatch, productId, qty])
return (
<div>CartScreen</div>
)
}
export default CartScreen
控制台显示类似这样的内容,它显示 url 参数中的 3,但显示一个空数组,它应该显示我已添加到购物车的产品数组。还有,GET http://localhost:3000/api/products/[object%20Object] 404 (Not Found)
是什么意思?仅供参考,产品是从 localhost:5000/api/products 中的 mongodb 获取的,但通过 localhost:3000
如果这有任何帮助,因为我也在使用 Redux,这是我的 addToCart 操作、redux 存储文件、购物车减速器。
import axios from "axios";
import { CART_ADD_ITEM } from "../constants/cartConstants";
export const addToCart = (id, qty) => async (dispatch, getState) => {
const {data} = await axios.get(`/api/products/${id}`)
dispatch({
type: CART_ADD_ITEM,
payload: {
product: data._id,
name: data.name,
image: data.image,
price: data.price,
countInStock: data.countInStock,
qty
}
})
localStorage.setItem('cartItems', JSON.stringify(getState().cart.cartItems))
}
import {createStore, combineReducers, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
import {composeWithDevTools} from 'redux-devtools-extension'
import { productListReducer, productDetailsReducer } from './reducers/productReducers'
import { cartReducer } from './reducers/cartReducers'
const reducer = combineReducers({
productList: productListReducer,
productDetails: productDetailsReducer,
cart: cartReducer,
})
const cartItemsFromLocalStorage = localStorage.getItem('cartItems') ? JSON.parse(localStorage.getItem('cartItems')) : []
const initialState = {
cart: {cartItems: cartItemsFromLocalStorage},
}
const middleware = [thunk]
const store = createStore(reducer,
initialState,
composeWithDevTools(applyMiddleware(...middleware)))
export default store
import {CART_ADD_ITEM} from "../constants/cartConstants"
export const cartReducer = (state = {cartItems: []}, action) => {
switch(action.type){
case CART_ADD_ITEM:
const item = action.payload
const existItem = state.cartItems.find(x => x.product === item.product)
if(existItem){
return{
...state,
cartItems: state.cartItems.map(x => x.product === existItem.product ? item : x),
}
} else {
return{
...state,
cartItems: [...state.cartItems, item]
}
}
default:
return state
}
}
您的 CartScreen
组件中只有一个小错误。您正在直接尝试使用 useParams
提取 productId
,但您不能这样做。因为 useParams
returns 一个 object
.
因此,如果您想使用 useParams
提取任何 dynamic value
。您必须 destructure
如下所示:
const { productId } = useParams()
这可以通过像这样重构 CartScreen.js 中的变量来解决:
const {productId} = useParams()
const useQty = useLocation()
const qty = useQty.search ? Number(useQty.search.split('=')[1]) : 1
为此:
const { id } = useParams();
const { search } = useLocation();
const productId = id;
const qty = search ? Number(search.split("=")[1]) : 1;
现在它在数组中显示产品详细信息,老实说我不知道这里发生了什么。