更新localStorage中的项目时遇到问题

时间:2019-06-24 15:57:04

标签: javascript reactjs local-storage

在这里用户的帮助下,我能够制作一个组件,但是现在我需要该组件的一种变体。该组件是一个递增/递减按钮,其中包含一些详细信息:
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中存在的项目数量并更新数量。我已经尝试了几天,什么也没做

1 个答案:

答案 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,
  });
}