从购物车中移除商品
Posted
技术标签:
【中文标题】从购物车中移除商品【英文标题】:Remove item from cart React 【发布时间】:2018-07-22 02:51:42 【问题描述】:关于以下代码,我有 2 个问题。我想在 React 中从我的购物车中删除特定物品。 (后端 Rails)。我知道拼接方法是最常用的方法之一,但在我的情况下,它不会删除特定的单击项,而是会一直删除最后一项,而不管我单击的是哪一项。 我的第二个问题是,即使项目确实以错误的方式被删除但仍然被删除,我的总计也没有得到更新。 这是代码:
import React, Component from 'react';
import BasketPic from './images/cart.png';
import StripePayment from './stripePayment';
class MainBasket extends React.Component
constructor(props)
super(props);
this.state =
toggle: true,
showBasket: false,
items: this.props.items
this.toggleBasket = this.toggleBasket.bind(this)
this.removeItemFromBasket = this.removeItemFromBasket.bind(this)
console.log(this.state.items)
toggleBasket()
this.setState(toggle: !this.state.toggle);
showCheckout()
this.setState(showBasket: !this.state.showBasket)
addItemToBasket(itemId)
fetch(`http://localhost:3000/books/$itemId`)
.then( item => item.json())
.then( item =>
this.state.items.push(item);
this.state.total += item.price;
this.setState(this.state);
)
removeItemFromBasket(itemId)
var itemToBeDeleted = this.state.items.indexOf(itemId)
var deleted = this.state.items.splice(itemToBeDeleted, 1)
this.setState(this.state)
render()
var count_items = this.props.items.length
var total = this.props.total
return(
<div className="basketInfo">
<div className="mainBasketDiv">
<img src=BasketPic onClick=this.toggleBasket />
<strong><p className="itemsCart">count_items</p></strong>
<strong><p className="checkOutConf">CheckOut</p></strong>
<div className="toggleDiv-" + this.state.toggle>
<h3>"Total: " + this.props.total</h3>
<span><h4>"Items: " + count_items </h4></span>
<hr/>
this.props.items.map( item =>
<div className="animated fadeInRight" key="item-" + item.id>
<h2>item.title</h2>
<h6 onClick=this.removeItemFromBasket className="remvProd">"Remove " + item.title</h6>
</div>
)
<button onClick=function()this.showCheckout().bind(this)> Check out</button>
</div>
</div>
<div className="container">
<div className="checkOutStripe-" + this.state.showBasket>
<div className="totalBar">
<p className="totalBarTypography"> Total this.props.items.length this.props.items.length < 2 ? "item" : "items"</p>
<p className="totalBarTypography"> Total this.props.total GBP</p>
</div>
<div className="row">
this.props.items.map(eachItem =>
<div className="col-sm" key="eachItem-" + eachItem.id>
<img src=eachItem.image.url className="checkOutImg"/>
<div className="prodDetails">
<h3>"Product: " + eachItem.title </h3>
<h3>"Price: " + eachItem.price </h3>
</div>
</div>
)
</div>
<div>
<StripePayment
description='BooksMania'
amount=total
/>
</div>
</div>
</div>
</div>
)
// module.exports = MainBasket;
export default MainBasket;
这是我设置总计和项目初始状态的代码:
import React, Component from 'react';
import BuyButton from './images/buyButton.jpg';
import MainBasket from './mainBasket';
import CheckOutBasket from './checkOutBasket';
import Reviews from './reviews';
class EachBook extends React.Component
constructor(props)
super(props);
this.state =
newReview: [],
items: [],
total: 0
seeAllReviews(bookId)
fetch(`http://localhost:3000/books/$bookId/reviews`)
.then( reviews => reviews.json())
.then( reviews =>
this.setState(
bookReviews: reviews
)
)
addReview(bookId)
fetch(`http://localhost:3000/books/$bookId/reviews`,
method: 'POST',
mode: 'cors',
body: JSON.stringify(comment: this.refs.comment.value),
headers: new Headers(
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRF-Token' : this.props.parent.props.parent.props.csrf
),
credentials: 'same-origin'
).then(response => response.json())
.catch(error => alert("There is something wrong with this request"))
.then( response =>
this.setState(newReview: response)
)
addItemToBasket(itemId)
fetch(`http://localhost:3000/books/$itemId`)
.then( item => item.json())
.then( item =>
this.state.items.push(item);
this.state.total += item.price;
this.setState(this.state);
)
render()
return(
<div>
<MainBasket items=this.state.items total=this.state.total parent=this/>
<div className="container">
this.props.singleBook.map(indBook =>
<div className="indBook" key=indBook.id>
<h1>indBook.title</h1> <br />
<h2>"Author: " + indBook.author</h2> <br />
<h4>"Genre: " + indBook.genre</h4>
<h4>"Price: " + indBook.price£</h4>
<img src=indBook.image.url />
<div className="button"><img src=BuyButton onClick=function()this.addItemToBasket(indBook.id).bind(this)/></div>
<div className="description">indBook.description</div>
<h3>this.state.newReview.comment</h3>
<div>
<h4>Leave a new review</h4>
<textarea ref="comment" type="text" placeholder='Tell us your thoughts '></textarea>
<button onClick= function()this.addReview(indBook.id).bind(this) >Submit</button>
</div>
</div>
)
</div>
</div>
)
export default EachBook;
非常感谢您的帮助!
【问题讨论】:
我对@987654323@ 了解不多,但是对于您的第一个问题,splice
期望索引作为第一个参数,因此您的this.state.items.splice(itemToBeDeleted, 1)
应该是this.state.items.splice(indexOfItemToBeDeleted, 1)
为什么要将你的项目传递给 MainBasket,然后将该数组存储在 MainBasket 中的状态中?这违反了 React 的核心原则之一,即“提升”状态到父组件。如果您确实继续在 MainBasket 中设置新状态,那么它已经与其当前父组件存储的项目表示不同步。如果出于某种原因这是您的意图,也许我错过了。
谢谢大家的及时回答@Subas
谢谢大家的及时回答@Subash 我认为 React 会理解特定元素的 id 也与理解它的索引相关,但显然不是,所以它删除了最后一个一直都是元素。我需要想办法找到索引。
@Daniel Zuzevich 我仍然是 React 的初学者(到目前为止大约 4 周)我确信我做的事情不是非常“最佳实践”,但我会纠正它们。我的 Main Basket 仅呈现 items 。项目的状态在我的 Each Book 组件中。但正如你所说,我把那个状态“提升”了,因为我需要参考项目的状态,这样我就可以对它们使用我的删除功能。你认为最好怎么做?非常感谢!
【参考方案1】:
你最大的问题是你正在改变状态中的items
,所以状态不会导致重新渲染。我会考虑使用filter
而不是splice
,然后像这样设置items
:
removeItemFromBasket(itemId)
const items = this.stat.items.filter(item => item.id !== itemId)
this.setState( items )
addItemToBasket
也应该有这个问题。你不应该改变state
,因为javascript 通过引用传递对象。您应该在 render
方法中使用 this.state.total
而不是 this.props.total
。
希望对您有所帮助。
【讨论】:
非常感谢这个解决方案,它确实有意义并且非常优雅,但不幸的是它什么也没做,我不明白原因。我使用 this.props.total 以便我可以在我的篮子图片和我的条带组件中呈现总计,因为实际状态会在每个 Book 组件中呈现。再次感谢您的宝贵时间:) 你可能想要重新组织你的组件并且让MainBasket
不是有状态的并且只是从你的EachBook
组件中传递所有的东西。问题是您正在更新state
,但您使用的是props
。您可能只想将一些处理程序传递给MainBasket
并让包装组件实际处理状态。以上是关于从购物车中移除商品的主要内容,如果未能解决你的问题,请参考以下文章