在这里用户的帮助下,我能够制作一个组件,但是现在我需要该组件的一种变体。该组件是一个递增/递减按钮,其中包含一些详细信息:
1-按钮位于来自API的数组中
2-递增/递减必须遵循库中定义的规则,即最大项目数
3-当其中一项存在时,带有“购买”按钮的页脚应自动出现
4-单击“购买”按钮时,这些项目将保存在localStorage中,并会打开一个新的屏幕,称为购物车,其中将包含相同的增减按钮,但在列表中选择的存储在localStorage中的项目按钮应增加/减少项目,然后单击“确认购买”按钮,必须更新localStorage。
直到第3项和第4项的一半可以完成,但是递增/递减按钮仍存在问题。以下是我的组件的代码
//Change Quantity Button
import React from 'react';
import './ChooseQuantity.css';
const ChooseQuantity = ({ value, onChange, additionEnabled }) => {
const shouldIncrement = additionEnabled;
const shouldDecrement = value > 0;
const decrement = () => {
if (shouldDecrement) {
onChange(value - 1);
}
}
const increment = () => {
if (shouldIncrement) {
onChange(value + 1);
}
}
const decrementButton = shouldDecrement ? (
<button className="minus" onClick={decrement}>
<i className="fas fa-minus"></i>
</button>
) : <div className="space-button"></div>
const incrementButton = shouldIncrement ? (
<button className='plus' onClick={increment}>
<i className="fas fa-plus"></i>
</button>
) : <div className="space-button"></div>
return (
<div>
{decrementButton}
<span className="qtd">{value}</span>
{incrementButton}
</div>
)
}
ChooseQuantity.defaultProps = {
value: 0,
additionEnabled: true,
}
export default ChooseQuantity
//Lot Component
import React from 'react'
import ChooseQuantity from '../../components/ChooseQuantity/ChooseQuantity.js';
const Lot = ({
ticketName,
ticketPrevenda,
lotUniqueNumber,
ticketUniqueNumber,
name,
lot,
lotType,
lotNumber,
lotPrice,
lotPriceTax,
lotQuantity,
onQuantityChange,
additionEnabled,
maxPurchase,
separator = '/',
quantity,
newValue,
}) => {
const onQuantityChangeInternal = (newValue) => {
onQuantityChange(ticketName, ticketPrevenda, ticketUniqueNumber, lotType, lotNumber, lotUniqueNumber, lotPrice, lotPriceTax, newValue, lotQuantity, maxPurchase)
}
return (
<div className="row">
<div className="col-8">
<h5 className="lot-name">{name}</h5>
<h5 className="lot-name">
{
lotType === 'U' ? 'Unissex ' : ''
}
{
lotType === 'M' ? 'Masculino ' : ''
}
{
lotType === 'F' ? 'Feminino ' : ''
}
({lotNumber}º Lote)
</h5>
<h6 className="lot-price">
R$ {lotPrice.replace('.', ',')} <br />
<small>(R$ {lotPrice.replace('.', ',')} + R$ {lotPriceTax.replace('.', ',')})</small>
</h6>
</div>
<div className="col-4">
<ChooseQuantity
value={lotQuantity}
onChange={onQuantityChangeInternal}
additionEnabled={additionEnabled}
maxPurchase={maxPurchase}
lot={lot}
lotPrice={lotPrice}
lotPriceTax={lotPriceTax}
lotQuantity={lotQuantity}
newValue={newValue}
/>
</div>
</div>
)
}
export default Lot
import React, { Component } from 'react';
import Lot from '../Cart/Lot';
import './Cart.css';
import '../../components/Css/App.css';
import Header from '../../components/Header/Header';
const separator = '/';
class Cart extends Component {
constructor(props) {
super(props);
this.state = {
cart: [],
lot: [],
qtd: 0,
events: null,
banner_app: null,
event_name: null,
priceTotal: null,
quantity: null,
selectedQuantities: {},
maxTotalItems: 0,
}
}
async componentDidMount() {
const cart = JSON.parse(localStorage.getItem('cart'));
await this.setState({ cart: cart });
this.setState({ events: this.state.cart.events });
this.setState({ banner_app: this.state.cart.events.banner_app });
this.setState({ event_name: this.state.cart.events.name });
this.setState({ priceTotal: this.state.cart.total.price });
this.setState({ quantity: this.state.cart.total.totalQuantity });
this.setState({ lot: this.state.cart.events.tickets.lot });
this.setState({ maxTotalItems: this.state.events.max_purchase });
this.setState({ selectedLots: this.state.cart.events.tickets.lot });
}
onQuantityChange = (ticketName, ticketPrevenda, ticketUniqueNumber, lotType, lotNumber, lotUniqueNumber, lotPrice, lotPriceTax, newValue, lotQuantity) => {
// console.log(lotQuantity);
this.setState(prevState => {
this.setState({
selectedQuantities: { ...prevState.selectedQuantities, [`${ticketName}${separator}${ticketPrevenda}${separator}${ticketUniqueNumber}${separator}${lotType}${separator}${lotNumber}${separator}${lotUniqueNumber}${separator}${lotPrice}${separator}${lotPriceTax}`]: newValue },
})
}, () => {
const selectedArray = Object.entries(this.state.selectedQuantities).map(
([key, quantity]) => {
const [ticketName, ticketPrevenda, ticketUniqueNumber, lotType, lotNumber, lotUniqueNumber, lotPrice, lotPriceTax] = key.split(separator)
const totalLotPrice = parseFloat(lotPrice + lotPriceTax);
const total = parseFloat(totalLotPrice * quantity);
return {
ticketName,
ticketPrevenda,
ticketUniqueNumber,
lotType,
lotNumber,
lotUniqueNumber,
lotPrice,
lotPriceTax,
quantity,
totalLotPrice,
total
}
},
)
// console.log(selectedArray);
// console.log(this.state.quantity);
//SOMANDO A QTD E ATUALIZANDO O STATE
// var lotQuantity = selectedArray.reduce(function(prevVal, elem) {
// console.log(elem.quantity)
// const lotQuantity = prevVal + elem.quantity;
// return lotQuantity;
// }, 0);
// this.setState({ qtd: lotQuantity });
// console.log(this.state.lotQuantity);
// //SOMANDO O TOTAL E ATUIALIZANDO O STATE
// var total = selectedArray.reduce(function(prevVal, elem) {
// const total = prevVal + elem.total;
// return total;
// }, 0);
// this.setState({priceTotal: total})
// //MOSTRAR/OCULTAR FOOTER
// if (lotQuantity > 0) {
// this.setState({ totalZero: true });
// } else {
// this.setState({ totalZero: false });
// }
// //OBJETO CART
// var lot = selectedArray;
// var tickets = {
// name: ticketName,
// prevenda: ticketPrevenda,
// unique_number: ticketUniqueNumber,
// lot: lot
// }
// total = {
// price: total,
// quantity: lotQuantity,
// };
// var events = {
// banner_app: this.state.event.banner_app,
// installments: this.state.event.installments,
// max_purchase: this.state.event.max_purchase,
// name: this.state.event.name,
// tickets: tickets,
// unique_number: this.state.event.unique_number,
// total_tickets: lotQuantity
// };
// var cart = { events: events, total: total };
// localStorage.setItem('cart', JSON.stringify(cart));
// localStorage.setItem('qtd', JSON.stringify(lotQuantity));
// console.log(lotQuantity);
// console.log(JSON.parse(localStorage.getItem('cart')));
//OBJETO CART
})
}
// getSelectedQuantity = (ticketName, ticketPrevenda, ticketUniqueNumber, lotType, lotNumber, lotUniqueNumber, lotPrice, lotPriceTax) => this.state.selectedQuantities[`${ticketName}${separator}${ticketPrevenda}${separator}${ticketUniqueNumber}${separator}${lotType}${separator}${lotNumber}${separator}${lotUniqueNumber}${separator}${lotPrice}${separator}${lotPriceTax}`];
//HERE IS THE FUNCTION THAT INCREMENT/DECREMENT ITEMS
getSelectedQuantity = (ticketName, ticketPrevenda, ticketUniqueNumber, lotType, lotNumber, lotUniqueNumber, lotPrice, lotPriceTax, lotQuantity) => {
// console.log(lotQuantity);
// console.log(this.state.selectedQuantities);
// lot.reduce(function(prevVal, elem) {
// // const soma = parseInt(elem) + parseInt(lotQuantity);
// console.log(elem)
// // return soma;
// }, 0);
// console.log(myLotQuantity);
// return myLotQuantity;
// console.log(this.state.selectedQuantities);
return this.state.selectedQuantities[
`${ticketName}${separator}${ticketPrevenda}${separator}${ticketUniqueNumber}${separator}${lotType}${separator}${lotNumber}${separator}${lotUniqueNumber}${separator}${lotPrice}${separator}${lotPriceTax}`
];
// return lotQuantity;
}
getAdditionEnabled = () => Object.values(this.state.selectedQuantities).reduce((acc, i) => acc + i, 0) < this.state.maxTotalItems;
onCheckoutButtonClick = () => {
const selectedArray = Object.entries(this.state.selectedQuantities).map(
([key, quantity]) => {
const [ticketName, ticketPrevenda, ticketUniqueNumber, lotType, lotNumber, lotUniqueNumber, lotPrice, lotPriceTax] = key.split(separator)
const totalLotPrice = parseFloat(lotPrice + lotPriceTax);
const total = parseFloat(totalLotPrice * quantity);
return {
ticketName,
ticketPrevenda,
ticketUniqueNumber,
lotType,
lotNumber,
lotUniqueNumber,
lotPrice,
lotPriceTax,
quantity,
totalLotPrice,
total
}
},
)
console.log(selectedArray);
}
render() {
return (
<div>
<Header Title="Carrinho" ToPage="/" />
<div className="cart">
<div className="container-fluid">
<div className="box-price">
<div className="row box-default ">
<div className="col col-price">
<h6>{this.state.quantity} INGRESSO{this.state.quantity > 1 ? 'S' : ''}</h6>
<h5>R$ {parseFloat(this.state.priceTotal).toFixed(2).replace('.', ',')}</h5>
</div>
</div>
</div>
<div className="box-default">
<div className="row no-margin">
<div className="col-12 col-image no-padding">
<img src={this.state.banner_app} alt="" />
</div>
<div className="col-12 no-padding">
<h5 className="event-name">{this.state.event_name}</h5>
</div>
</div>
{
this.state.lot.map((lot, l) =>
// <div className="row" key={l}>
// <div className="col-8">
// <h5 className="lot-name">{lot.name}</h5>
// <h5 className="lot-name">
// {
// lot.lotType === 'U' ? 'Unissex ' : ''
// }
// {
// lot.lotType === 'M' ? 'Masculino ' : ''
// }
// {
// lot.lotType === 'F' ? 'Feminino ' : ''
// }
// ({lot.lotNumber}º Lote)
// </h5>
// <h6 className="lot-price">
// R$ {lot.lotPrice.replace('.', ',')} <br />
// <small>(R$ {lot.lotPrice.replace('.', ',')} + R$ {lot.lotPriceTax.replace('.', ',')})</small>
// </h6>
// </div>
// <div className="col-4">
// <ChooseQuantity
// value={this.getSelectedQuantity(lot.quantity)}
// onChange={this.onQuantityChange}
// additionEnabled={this.additionEnabled}
// maxPurchase={this.state.events.max_purchase}
// lotPrice={lot.lotPrice}
// lotPriceTax={lot.lotPriceTax}
// lotQuantity={lot.lotQuantity}
// />
// </div>
// <div className="col-12">
// {this.state.lot.length > 1 ? <hr /> : ''}
// </div>
// </div>
<div key={l}>
<Lot
events={this.state.events}
ticketName={this.state.cart.events.tickets.name}
ticketPrevenda={this.state.cart.events.tickets.prevenda}
ticketUniqueNumber={this.state.cart.events.tickets.unique_number}
lotUniqueNumber={lot.lotUniqueNumber}
lotName={lot.name}
lotType={lot.lotType}
lotNumber={lot.lotNumber}
lotPrice={lot.lotPrice}
lotPriceTax={lot.lotPriceTax}
onQuantityChange={this.onQuantityChange}
maxPurchase={this.state.events.max_purchase}
lotQuantity={this.getSelectedQuantity(this.state.cart.events.tickets.name, this.state.cart.events.tickets.prevenda, this.state.cart.events.tickets.unique_number, lot.lotType, lot.lotNumber, lot.lotUniqueNumber, lot.lotPrice, lot.lotPriceTax, lot.quantity)}
// quantity={lot.quantity}
additionEnabled={this.getAdditionEnabled()}
/>
{this.state.lot.length > 1 ? <hr /> : ''}
</div>
)
}
<div className="row cart-footer" style={{ marginRight: '-15px', marginLeft: '-15px', backgroundColor: '#f4f7fa' }}>
<button className="col col-purchase" to="/cart" style={{ justifyContent: 'center', alignItems: 'center' }} onClick={this.onCheckoutButtonClick}>
Confirmar Comprar
</button>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default Cart;
在我输入的getSelectedQuantity函数中
return this.state.selectedQuantities[
`${ticketName}${separator}${ticketPrevenda}${separator}${ticketUniqueNumber}${separator}${lotType}${separator}${lotNumber}${separator}${lotUniqueNumber}${separator}${lotPrice}${separator}${lotPriceTax}`
];
它更新增量/减量按钮上的项目,但是我需要它来显示localStorage中存在的项目数量并更新数量。我已经尝试了几天,什么也没做
答案 0 :(得分:1)
这可能不是您所遇到问题的完整答案,但是您正在您的componentDidMount中引起流血的地狱,尤其是多次调用this.setState()时。记住一件事-每次调用this.setState都在重新渲染组件。
另外,this.setState()不会返回承诺,因此await this.setState({...})
没有任何意义。
因此,您组件的第一个改进将是:
componentDidMount() {
const cart = JSON.parse(localStorage.getItem('cart'));
const {
events,
events: { tickets },
total
} = cart;
this.setState({
cart,
events,
banner_app: events.banner_app,
event_name: events.event_name,
priceTotal: total.price,
quantity: total.totalQuantity,
lot: tickets.lot,
maxTotalItems: events.max_purchase,
selectedLots: tickets.lot,
});
}