React类组件基于React-Redux实现购物车移除/清空功能求助
购物车移除/清空功能实现方案
1. 调整Redux侧逻辑
首先新增移除、清空相关的action定义和reducer处理逻辑,和你已有的加入购物车逻辑对齐即可:
// action类型定义 export const REMOVE_ITEM_FROM_CART = 'REMOVE_ITEM_FROM_CART' export const CLEAR_CART = 'CLEAR_CART' // action creator export const removeItemFromCart = (productId) => { return { type: REMOVE_ITEM_FROM_CART, payload: productId } } export const clearCart = () => { return { type: CLEAR_CART } }
// 购物车reducer逻辑更新 const initialState = { cart: [] } const cartReducer = (state = initialState, action) => { switch(action.type) { case 'ADD_CART': // 原有添加商品的逻辑直接保留 return { ...state, cart: [...state.cart, action.payload] } case REMOVE_ITEM_FROM_CART: return { ...state, // 过滤掉ID匹配的商品,其余保留 cart: state.cart.filter(item => item.id !== action.payload) } case CLEAR_CART: return { ...state, cart: [] } default: return state } }
2. 修正Cart组件代码
注意你原有代码的Remove按钮放在了map循环外部,只会渲染1个,需要移到map循环内部的每行tr里,才能实现每行商品对应一个移除按钮;同时react内的class属性要写为className,避免报错
import React, { Component } from "react" import { Card, CardBody, CardHeader, CardTitle, Row, Col, Button } from "reactstrap" import PanelHeader from "components/PanelHeader/PanelHeader.js" import { connect } from "react-redux"; // 替换为你实际的action文件路径 import { removeItemFromCart, clearCart } from 'redux/actions/cartActions' class Cart extends Component { render () { const cart = this.props.cart return ( <> <PanelHeader size="sm" /> <div className="content"> <Row> <Col xs={12}> <Card> <CardHeader className="d-flex justify-content-between align-items-center"> <CardTitle tag="h4">Products List</CardTitle> {/* 新增清空购物车按钮 */} <Button color="warning" onClick={() => this.props.clearCart()} disabled={cart.length === 0} > 清空购物车 </Button> </CardHeader> <CardBody> <table className="table table-striped table-hover"> <thead> <tr> <th scope="col"><strong>#</strong></th> <th scope="col"><strong>Name</strong></th> <th scope="col"><strong>Code Item</strong></th> <th scope="col"><strong>Quantity</strong></th> <th scope="col"><strong>Price Total</strong></th> <th scope="col"><strong>Operation</strong></th> </tr> </thead> <tbody> {cart.length > 0 && cart.map((cartItem, index) => ( <tr key={cartItem.id}> <th scope="row">{index + 1}</th> <td>{cartItem.title}</td> <td>{cartItem.code}</td> <td>{cartItem.quantity}</td> <td>{cartItem.price}</td> {/* 移除按钮移到每行内部,传入当前商品ID */} <td> <button onClick={() => this.props.removeItemFromCart(cartItem.id)} className="btn btn-danger cart-button px-4" > Remove </button> </td> </tr>))} {cart.length === 0 && <tr><td colSpan={6} className="text-center">购物车暂无商品</td></tr>} </tbody> </table> </CardBody> </Card> </Col> </Row> </div> </> ) } } const mapStateToProps = (state)=> { return { cart: state.cart } } const mapDispatchToProps = (dispatch) => { return { addCart: (product) => {dispatch(addCart(product))}, // 新增两个操作的dispatch映射 removeItemFromCart: (productId) => dispatch(removeItemFromCart(productId)), clearCart: () => dispatch(clearCart()) } } export default connect(mapStateToProps, mapDispatchToProps)(Cart);
补充疑问解答
- 问题1:
mapStateToProps和mapDispatchToProps是类组件接入Redux的必需API。mapStateToProps负责把Redux store里的状态映射为组件的props,mapDispatchToProps负责把触发store更新的dispatch方法映射为组件的props,只要你用Redux管理购物车状态,类组件场景下这两个方法是必须的。如果是函数组件可以用useSelector、useDispatch两个hooks替代,就不需要写这两个方法了。 - 问题2:报错确实和Redux专属语法有关。
connect、mapStateToProps、mapDispatchToProps都是react-redux库的专属能力,脱离Redux场景直接改普通组件的话,组件无法获取cart属性和对应的操作方法,就会出现变量未定义、prop为空之类的报错。
内容的提问来源于stack exchange,提问作者Shpongle
相关产品推荐
相关产品推荐

