Reputation: 366
I got a component that is render in a array. This component just show 2 buttons and a input text. This buttons increment/decrease 1 item (see the image). I have some data coming from a API and one of this item limit the purchase. I need to hide the increment button when the limit is higher and show when limit is lower. I can do this, but my problem is that just occur with one button and not with all the buttons in array
//My Buttons increment/decrease component
import React, { Component } from 'react';
import api from '../../components/Util/api.js';//para requisições
import './ChooseQuantity.css';
var cart = {};
var total = {};
var events = {};
var tickets = [];
var quantity = [];
class ChooseQuantity extends Component {
constructor(props) {
super(props);
this.state = {
qtd: 0,
showAddButton: true,
showRemoveButton: true,
}
}
addItem() {
// quantity = [];
localStorage.removeItem('quantity');
this.setState({ showRemoveButton: false });
this.setState({ qtd: this.state.qtd += 1 });
quantity.push(parseInt(this.state.qtd));
localStorage.setItem('quantity', quantity.length);
console.log(this.state.showAddButton);
// if (tickets.indexOf(this.props.tickets)) {
// tickets.push(this.props.tickets);
// }
// var price = this.props.price * this.state.qtd;
// total = { price: price, quantity: this.state.qtd };
// events = {
// banner_app: this.props.banner_app,
// installments: this.props.installments,
// max_purchase: this.props.max_purchase,
// name: this.props.event_name,
// tickets: tickets,
// unique_number: this.props.unique_number
// };
// cart = { events: events, total: total };
// localStorage.setItem('cart', JSON.stringify(cart));
// console.log(localStorage.getItem('quantity'));
if (localStorage.getItem('quantity') >= this.props.max_purchase) {
this.setState({ showAddButton: false });
}
}
removeItem() {
if (this.state.qtd > 0) {
this.setState({ qtd: this.state.qtd -= 1 });
}
if (this.state.qtd === 0) {
quantity = [];
quantity.pop();
quantity.length = '';
localStorage.removeItem('quantity');
// this.setState({ showRemoveButton: true });
} else{
// this.setState({ showAddButton: true });
localStorage.setItem('qtd', this.state.qtd);
quantity.push(parseInt(this.state.qtd));
// quantity = JSON.parse(localStorage.getItem('quantity'));
localStorage.setItem('quantity', this.state.qtd);
}
console.log(localStorage.getItem('quantity'));
if(localStorage.getItem('quantity') >= this.props.max_purchase){
// this.setState({ showRemoveButton: false });
}
// cart = JSON.parse(localStorage.getItem('cart'));
// if (cart.events.tickets.indexOf(this.props.tickets)) {
// localStorage.removeItem('cart');
// console.log('retirou');
// var price = this.props.price * this.state.qtd;
// total = { price: price, quantity: this.state.qtd };
// events = {
// banner_app: this.props.banner_app,
// installments: this.props.installments,
// max_purchase: this.props.max_purchase,
// name: this.props.event_name,
// tickets: tickets
// };
// cart = { events: events, total: total };
// localStorage.setItem('cart', JSON.stringify(cart));
// console.log(cart.events.tickets.indexOf(this.props.tickets));
// }
// console.log(cart.events.tickets);
console.log(this.state.showAddButton);
}
componentDidMount() {
// const { id } = this.props.event_id;
// api.get(`event/${this.props.event_id}`)
// .then(res => {
// const event = res.data.data;
// console.log(event);
// this.setState({ event });
// this.setState({ dates: event.dates })
// this.state.dates.map((date, i) =>
// this.setState({ tickets: this.state.dates[i].tickets})
// )
// this.state.tickets.map((ticket, i) =>
// this.setState({ lots: ticket.lot})
// )
// })
}
render() {
return (
<div>
{
!this.state.showRemoveButton ?
<button className="minus" onClick={() => this.removeItem()}>
<i className="fas fa-minus"></i>
</button>
:
<div className="space-button"></div>
}
<input className="qtd" type="text" value={this.state.qtd} name='qtd' onChange={() => this.handleChange()} readOnly />
{
this.state.showAddButton ?
<button className='plus' onClick={() => this.addItem()} >
<i className="fas fa-plus"></i>
</button>
:
<div className="space-button"></div>
}
</div>
)
}
}
export default ChooseQuantity;
import React, { Component } from 'react';
import api from '../../components/Util/api.js';//para requisições
import Header from '../../components/Header/Header';
import { Link } from 'react-router-dom';
import './Event.css';
import '../../components/Css/App.css';
import ChooseQuantity from '../../components/ChooseQuantity/ChooseQuantity.js';
class Event extends Component {
constructor(props){
super(props);
this.state = {
event: {},
dates: [],
tickets: [],
choose_quantity: 0,
qtd: 0,
}
}
componentDidMount() {
const { id } = this.props.match.params;
api.get(`event/${id}`)
.then(res => {
const event = res.data.data;
this.setState({ event });
console.log(event);
this.setState({ dates: event.dates })
this.state.dates.map((date, i) =>
this.setState({ tickets: this.state.dates[i].tickets})
)
this.state.tickets.map((ticket, i) =>
this.setState({ lots: ticket.lot})
)
})
}
render() {
return (
<div>
<Header Title={this.state.event.name} ToPage="/" />
<div className="container-fluid padding-15 event">
<div className="mt-5">
<img className="card-img-top" src={this.state.event.banner_app} alt={this.state.event.name} />
<div className="row no-margin mb-3">
<div className="col-8 no-padding">
<h1 className="event-title">{this.state.event.name}</h1>
<h1 className="event-place">
<i className="fas fa-pin"></i>
{this.state.event.place}
</h1>
</div>
<div className="col-4 event-date-col align-items">
<span className="event-date" id="event-date">
</span>
{ this.state.dates.map((date, i) =>
<span className="event-date" key={i}>
{ date.date }
</span>
)}
</div>
</div>
{
this.state.tickets.map((ticket, i) => (
<div key={i}>
<div className="row">
<div className="col">
<h3 className="ticket-name">{ ticket.name }</h3>
</div>
</div>
{ticket.lot.map((lot, j) =>
<div className="row" key={i}>
<div className="col-8">
<h5 className="lot-name">{ lot.name }</h5>
<h6 className="lot-price">
R$ { lot.price.replace('.', ',') } <br />
<small>(R$ { lot.price.replace('.', ',') } + R$ { lot.price_tax.replace('.', ',') })</small>
</h6>
</div>
<div className="col-4">
<ChooseQuantity event_id={this.state.event.id} unique_number={ lot.unique_number } price={ lot.price } banner_app={ this.state.event.banner_app } max_purchase={this.state.event.max_purchase} event_name={this.state.event.name} tickets={ ticket.lot } />
</div>
</div>
)}
<hr />
</div>
)
)
}
<div className="row mt-5">
<div className="col">
<h6 className="text-default">Descrição</h6>
</div>
</div>
<div className="row">
<div className="col" dangerouslySetInnerHTML={{__html:this.state.event.description}}></div>
</div>
</div>
</div>
<div className="row cart-footer">
<div className="col col-price">
<h6>3 INGRESSOS</h6>
<h5>R$ 16,00</h5>
</div>
<Link className="col col-purchase" to="/">
Comprar
</Link>
</div>
</div>
)
}
}
export default Event;
Upvotes: 0
Views: 1879
Reputation: 676
I created a sample small project with the functionality that you need.
Basically, you need to keep the state in one single component - the parent component. You shouldn't use localStorage. I used a pair of ticket.uniqueId and lot.uniqueId as a key for selectedValue:
state = {
selectedQuantities: {
'ticket_1/lot_1': 3,
'ticket_1/lot_2': 4,
}
}
Then pass the selection to ChooseQuantity
component
<ChooseQuantity
...
value={this.state.selectedQuantities[`${ticketUniqueId}${separator}${lotUniqueId}`}
/>
Then the ChooseQuantity
component will look similar to this:
import React from 'react'
const ChooseQuantity = ({maxValue, value, onChange}) => {
const shouldIncrement = value < maxValue
const shouldDecrement = value > 0
const decrement = () => {
if (shouldDecrement) {
onChange(value - 1)
}
}
const increment = () => {
if (shouldIncrement) {
onChange(value + 1)
}
}
const decrementButton = shouldDecrement ? (
<button style={buttonStyle} onClick={decrement}>
-
</button>
) : null
const incrementButton = shouldIncrement ? (
<button style={buttonStyle} onClick={increment}>
+
</button>
) : null
return (
<div style={containerStyle}>
{decrementButton}
<span style={valueStyle}>{value}</span>
{incrementButton}
</div>
)
}
ChooseQuantity.defaultProps = {
value: 0,
maxValue: 4,
}
const containerStyle = {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
}
const buttonStyle = {
height: '20px',
margin: '0 5px',
}
const valueStyle = {
margin: '0 5px',
}
export default ChooseQuantity;
In App component (parent) there's a Checkout
button where the state.selectedQuantities
object is transformed into an array of objects so that you could use it to create an API request to the backend to complete the order:
[
{
"ticketId": "ticket_1",
"lotId": "lot_1",
"quantity": 3,
},
{
"ticketId": "ticket_1",
"lotId": "lot_2",
"quantity": 4,
},
]
Here is a working example: https://codesandbox.io/s/react-codesandbox-tsrwc
Side note: Avoid using this.setState()
after this.setState()
so many times. Try use this.setState()
one time per event (click, hover, API response etc)
Upvotes: 1
Reputation: 5141
I noticed that you are using
!this.state.showRemoveButton ?
while on your add button
this.state.showAddButton ?
You should try removing the ! for the showRemoveButton.
Upvotes: 1