Edinho Rodrigues
Edinho Rodrigues

Reputation: 366

Show/Hide a element by condition in a array

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;

enter image description here

Upvotes: 0

Views: 1879

Answers (2)

Radu Nemerenco
Radu Nemerenco

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

jegtugado
jegtugado

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

Related Questions