javascript - 被删除组件的状态覆盖下一个组件
问题描述
我有父组件,名称为 ShoppingCartDetail。它将渲染许多子组件,名称为 ShoppingCartProduct,每个子组件显示产品的数量,它具有更改数量的按钮,以及一个用于从添加到购物车的产品数组中删除当前产品的按钮(如购物网站上的购物车) .
我的问题是:如果改变产品的数量,印刷机将被移除。被移除组件的状态将覆盖下一个组件的状态。如果我不增加/减少,没有问题发生。
我已经向子组件添加了 key 属性,但它没有帮助。如果您能提供任何建议,我将不胜感激。
1. ShoppingCartDetail.js(父级):
import React from 'react';
import {NavLink} from "react-router-dom";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faReplyAll, faLock} from "@fortawesome/free-solid-svg-icons";
import {connect} from "react-redux";
import ShoppingCartProduct from './ShoppingCartProduct';
const ShoppingCartDetail = (props) => {
const {Cart, Products, Currency} = props.Data;
// format thounds seperator
function formatNumber(num) {
return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')
}
/* Remove duplicate product in Cart arr based on ID*/
const currentCart = [...Cart];
// get ID list of current Cart
let currentIdList = [];
currentCart.forEach((product) => {
currentIdList.push(product.id);
})
// removed duplicated ID
let removedDuplicateIdList = [];
currentIdList.forEach((id) => {
if (!removedDuplicateIdList.includes(id)){
removedDuplicateIdList.push(id)
}
})
// create product array base on ID list, use this array to render shopping cart
let splicedProductsList = [];
removedDuplicateIdList.forEach((id) => {
Products.forEach((product)=>{
if (product.id === id){
splicedProductsList.push(product)
}
})
})
/* End remove duplicate product in Cart arr based on ID*/
// Calculate total amount of Shopping Cart (re-use currentIdList)*/
var totalAmount = 0;
currentIdList.forEach((id) => {
Products.forEach((product)=>{
if (product.id === id){
totalAmount += product.price // (default is USD)
}
})
})
// fortmat money (currency and operator and decimal)
const showMoneyTotal = (currency, amount) => {
switch (currency) {
case "USD":
return "$ " + formatNumber((amount).toFixed(2))
case "EUR":
return "€ " + formatNumber((amount * 0.84).toFixed(2))
case "GBP":
return "£ " + formatNumber((amount * 0.76).toFixed(2))
default:
return "$ " + formatNumber((amount).toFixed(2))
}
}
return (
<section className="shopping-cart-detail">
<div className="container">
<div className="row title">
<div className="col">
<h4>Your Shopping Cart</h4>
</div>
<div className="col-auto">
<NavLink
to = "/all-collection"
exact = {true}
>
<FontAwesomeIcon icon = {faReplyAll} className="icon"/>
Continue Shopping
</NavLink>
</div>
</div>
<div className="row shopping-cart-content">
<div className="col-6 order">
<div className="content">
<div className="title">Order Summary</div>
<div className="info">
<div className="container">
{
splicedProductsList.map((product, index) => {
return (
<ShoppingCartProduct Product = {product} key = {product}></ShoppingCartProduct>
)
})
}
</div>
</div>
</div>
</div>
<div className="col-3 total-amount">
<div className="content">
<div className="title">Your Cart Total</div>
<div className="info">
<div className="money">
<span> {showMoneyTotal(Currency.currency, totalAmount)} </span>
</div>
<div className="check-out">
<div className="wrap">
<FontAwesomeIcon icon = {faLock} className = "icon"/>
<NavLink
to="/"
exact={true}
>
Proceed To Checkout
</NavLink>
</div>
</div>
<div className="payment-card">
<img
alt="payment-card"
src={require("../../Assets/images/section-shopping-cart-detail/payment.webp")}
/>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
);
};
const mapStateToProps = (state) => {
return {
Data: state
}
}
export default connect(mapStateToProps)(ShoppingCartDetail)
2.ShoppingCartProduct.js(子)
import React, {useState} from 'react';
import {NavLink} from "react-router-dom";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faPen, faTimesCircle } from "@fortawesome/free-solid-svg-icons";
import {connect} from "react-redux";
import urlSlug from "url-slug";
const ShoppingCartProduct = (props) => {
const {Cart, Currency} = props.Data;
const {Product, dispatch} = props;
// count quantity of a product in Shopping Cart
const countProduct = (id) => {
let count = 0;
Cart.forEach((product) => {
if (product.id === id) {
count += 1;
}
})
return count;
}
const [state, setState] = useState({
update_quantity: countProduct(Product.id),
name: Product.name
})
// increase quantity when click plus button
const increaseAddedAmount = () => {
setState((prevState) => {
return {
...prevState,
update_quantity: prevState.update_quantity + 1
}
})
}
// decrease quantity when click substract button
const decreaseAddedAmount = () => {
if (state.update_quantity > 0) {
setState((prevState) => {
return {
...prevState,
update_quantity: prevState.update_quantity - 1
}
})
}
}
return (
<div className={`row product-row ${Product.name}`} key = {Product}>
<div className="col-2 img">
<img
alt="product"
src = {Product.main__image}
/>
</div>
<div className="col-10 product-detail">
<div className="row name">
<div className="col">
<NavLink
to = {`/product/${urlSlug(Product.name)}`}
exact = {true}
>
{Product.name}
</NavLink>
</div>
</div>
<div className="row price">
<div className="col">{showMoney(Currency.currency, 1, Product)}</div>
</div>
<div className="row quantity-title">
<div className="col">
Quantity
</div>
</div>
<div className="row quantity-row">
<div className="col-3 quantity">
<div className="wrap">
<span
className="decrease"
onClick = {()=>{decreaseAddedAmount()}}
>-</span>
<span className='count'>
{state.update_quantity}
</span>
<span
className="increase"
onClick = {()=>{increaseAddedAmount()}}
>+</span>
</div>
</div>
<div className="col-3 update-quantity">
<div
className="wrap"
onClick = {()=>dispatch({type: "UPDATE", id: Product.id, quantity: state.update_quantity})}
>
<FontAwesomeIcon icon = {faPen} className="icon"/>
Update
</div>
</div>
<div className="col-3 remove-product">
<div
className="wrap"
onClick = {()=>{dispatch({type: "REMOVE", id: Product.id})}}
>
<FontAwesomeIcon icon = {faTimesCircle} className="icon"/>
Remove
</div>
</div>
</div>
</div>
</div>
);
};
const mapStateToProps = (state) => {
return {
Data: state
}
}
export default connect(mapStateToProps)(ShoppingCartProduct)
解决方案
为简单起见,尝试将点击的产品作为道具传递,然后使用名为 findIndex() 的 javascript 方法在 Cart 数组中查找点击产品的 id 并将其存储在变量中。获得 id 后,然后使用 splice 生成一个新的购物车数组,而没有您找到的那个 id。您可以使用此代码片段作为参考。
const index = this.state.cart.findIndex(
(cartItem) => cartItem.id === clickedProduct.id
);
let newCart = [...this.state.cart];
if (index >= 0) {
newCart.splice(index, 1);
}
推荐阅读
- sql-server - Transfer data from Azure SQL VM to Azure SQL Database
- angular - Angular: Calling SelectedTabChange only for rendered tabs
- python - A receiver that can receive both TCP images and UDP texts
- google-cloud-platform - Cloud Function is taking too long to send a message to PubSub
- vulkan - Vulkan:实例和设备扩展之间的区别?
- database - Config Redis to use disk automatically
- php - Load data from csv and ignore duplicate record based on multiple column match mysql
- python - 如何检查第二个子列表中是否存在元素?
- json - 如何将 jsonschema 间接枚举源用于扩展选择参数?
- linux - Linux 变量/数组赋值中的 Bash 脚本