javascript - (React 和 Redux)将商品添加到购物车的问题
问题描述
我正在关注一个教程,我们正在构建一个购物车,但尚未完成,但我想在继续教程之前解决这个问题。
问题是,当我尝试将任何物品添加到购物车时,购物车仍然在说我的购物车是空的。您可以在下面这张图片的 url 中注意到,我已将 id 编号为 1 的商品添加到购物车中,并且数量 (qty) 也是 1。
但购物车在添加商品后不应响应此类消息。在代码所在的这个阶段,响应应该只是一个空白页。
当我尝试控制台时,这还没有工作。记录 cartItems - 这对我来说是一个空数组,但讲师正在接收有关产品的数据,这些数据已添加到购物车中。所以这可能是一个线索。
如果您能看到任何提示或解决方案,请查看以下文件并告诉我。
CartScreen.js -
import React, {useEffect} from 'react'
import { Link } from 'react-router-dom'
import { useDispatch, useSelector } from 'react-redux'
import { Row, Col, ListGroup, Image, Form, Button, Card } from 'react-bootstrap'
import Message from '../components/Message'
import { addToCart } from '../actions/cartActions'
function CartScreen({ match, location, history }) {
const productId = match.params.div
const qty = location.search ? Number(location.search.split('=')[1]) : 1
const dispatch = useDispatch()
const cart = useSelector(state => state.cart)
const { cartItems } = cart
useEffect(() =>{
if(productId){
dispatch(addToCart(productId, qty))
}
}, [dispatch, productId, qty])
return (
<Row>
<Col md={8}>
<h1>Shopping Cart</h1>
{cartItems.length === 0 ? (
<Message variant='info'>
Your cart is empty <Link to='/'>Go Back</Link>
</Message>
) : (
<listGroup variant='flush'>
</listGroup>
)}
</Col>
<Col md={4}>
</Col>
</Row>
)
}
export default CartScreen
cartActions.js -
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))
}
cartReducers.js -
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
}
}
cartConstants.js -
export const CART_ADD_ITEM = 'CART_ADD_ITEM'
export const CART_REMOVE_ITEM = 'CART_REMOVE_ITEM'
store.js -
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 cartItemsFromStorage = localStorage.getItem('cartItems') ?
JSON.parse(localStorage.getItem('cartItems')) : []
const initialState = {
cart: { cartItems: cartItemsFromStorage }
}
const middleware = [thunk]
const store = createStore(reducer, initialState,
composeWithDevTools(applyMiddleware(...middleware)))
export default store
ProductScreen.js -
import React, { useState, useEffect } from "react";
import { useDispatch, useSelector } from 'react-redux'
import { Link } from "react-router-dom";
import { Row, Col, Image, ListGroup, Button, Card, Form } from "react-bootstrap";
import Rating from "../components/Rating";
import Loader from "../components/Loader";
import Message from "../components/Message";
import { listProductDetails } from '../actions/productActions'
function ProductScreen({ match, history }) {
const[qty, setQty] = useState(1)
const dispatch = useDispatch()
const productDetails = useSelector(state => state.productDetails)
const { loading, error, product } = productDetails
useEffect(() => {
dispatch(listProductDetails(match.params.id))
},[dispatch, match])
const addToCartHandler = () => {
history.push(`/cart/${match.params.id}?qty=${qty}`)
}
return (
<div>
<Link to="/" className="btn btn-light my-3">
Go Back
</Link>
{loading ?
<Loader/>
: error
? <Message variant='danger'>{error}</Message>
:(
<Row>
<Col md={6}>
<Image src={product.image} alt={product.name} fluid />
</Col>
<Col md={3}>
<ListGroup variant="flush">
<ListGroup.Item>
<h3>{product.name}</h3>
</ListGroup.Item>
<ListGroup.Item>
<Rating
value={product.rating}
text={`${product.numReviews} reviews`}
color={"#f8e825"}
/>
</ListGroup.Item>
<ListGroup.Item>Price: ${product.price}</ListGroup.Item>
<ListGroup.Item>Description: {product.description}</ListGroup.Item>
</ListGroup>
</Col>
<Col md={3}>
<Card>
<ListGroup variant="flush">
<ListGroup.Item>
<Row>
<Col>Price:</Col>
<Col>
<strong>${product.price}</strong>
</Col>
</Row>
</ListGroup.Item>
<ListGroup.Item>
<Row>
<Col>Status:</Col>
<Col>
{product.countInStock > 0 ? "In Stock" : "Out of Stock"}
</Col>
</Row>
</ListGroup.Item>
{product.countInStock > 0 && (
<ListGroup.Item>
<Row>
<Col>Qty</Col>
<Col xs='auto' className='my-1'>
<Form.Control
as="select"
value={qty}
onChange={(e) => setQty(e.target.value)}
>
{
[...Array(product.countInStock).keys()].map((x) => (
<option key={x + 1} value={x + 1}>
{x + 1}
</option>
))
}
</Form.Control>
</Col>
</Row>
</ListGroup.Item>
)}
<ListGroup.Item>
<Button
onClick={addToCartHandler}
className="btn-block"
disabled={product.countInStock == 0}
type="button"
>
Add to Cart
</Button>
</ListGroup.Item>
</ListGroup>
</Card>
</Col>
</Row>
)
}
</div>
);
}
export default ProductScreen;
解决方案
这是错误:
const productId = match.params.div
它应该是“id”而不是 div
const productId = match.params.id
推荐阅读
- javascript - 如何使用与增加相同的数字来降低价格?
- c++ - 为什么将匿名堆栈分配数组传递给 unique_ptr 不会导致段错误?
- python - 为什么在 python 中将集合初始化为 `{*()}` 比 `set()` 快?
- javascript - 你能修改 NextJS 的挂载元素或向 __next div 添加类吗?
- html - 更改浏览器大小时图像位于文本之上
- github - 使用 azure rest api 创建 GitHub 服务连接给出错误
- python - 循环Python的这种语法是什么
- flutter - FutureBuilder 中的构建器在 Flutter 中不起作用
- java - 使用自己的方法结果再次调用 Spring Controller 方法
- php - 我怎样才能在另一个中嵌入一个 echo statmtement?