【问题标题】:React Typescript Order Form calculation error on change更改时反应 Typescript 订单计算错误
【发布时间】:2020-09-14 19:38:24
【问题描述】:

我正在使用 react typescript 构建订单。该表单允许用户输入quantityunit price,并选择项目是否为taxable

我为这个示例简化了我的代码,只展示了添加 1 或 2 个项目的能力。但对于最终产品,他的用户将能够添加大约 10-15 项。所以每个字段将有 15 个。这将被标记为quantity1quantity2quantity3 等。

因此,一旦用户选择了数量、单价以及商品是否应纳税。我有一个计算 total extended price 的字段,它只是 quantity * unit price

我也有两个字段。一种为所有项目添加所有税款(这只是用户选择应税到是的项目)。另一个是包含所有税费的总价。

现在一切正常。但以下是我面临的三个问题。当用户进行更改时,问题就开始了。

  • 如果用户选择taxableYes,然后返回No。价格调整了,但Estimated Sales Tax 仍然没有反映变化。

  • 如果用户选择 5 作为数量,然后更改为 4,再变回 5,则税款会增加两次。

  • 如果在将税款添加到总金额时,税款最终是小数,则数学错误。

这是我的代码:

import * as React from 'react';

export class Screen1 extends React.Component<{}, {
    Quantity: number, 
    UnitPrice: number,
    ExtendedPrice: number,
    Taxable1: string,
    TaxAmount1: number,
    Quantity2: number, 
    UnitPrice2: number,
    ExtendedPrice2: number,
    Taxable2: string,
    TaxAmount2: number,
    EstimatedTotal: number;
    EstimatedSalesTax: number;
}> {

    constructor(props) {
        super(props);
        this.state = {
            Quantity: null,
            UnitPrice: null,
            ExtendedPrice: null,
            Taxable1: '',
            TaxAmount1: null,
            Quantity2: null,
            UnitPrice2: null,
            ExtendedPrice2: null,
            Taxable2: '',
            TaxAmount2: null,                   
            EstimatedTotal: null,
            EstimatedSalesTax: 0,                       
        };

        this.handleChangeQuantity = this.handleChangeQuantity.bind(this);
        this.handleChangeUnitPrice = this.handleChangeUnitPrice.bind(this);
        this.handleChangeExtendedPrice = this.handleChangeExtendedPrice.bind(this);
        this.handleChangeTaxable1 = this.handleChangeTaxable1.bind(this);

        this.handleChangeEstimatedTotal = this.handleChangeEstimatedTotal.bind(this);
        this.handleChangeEstimatedSalesTax = this.handleChangeEstimatedSalesTax.bind(this);

    }


    handleChangeQuantity = async (event: any) => {
        const value = parseInt(event.target.value)
        await this.setState({ Quantity: value })
        console.log(value);
        this.handleChangeExtendedPrice()
      }

    handleChangeUnitPrice = async (event: any) => {
        const value = parseInt(event.target.value)
        await this.setState({ UnitPrice: value })
        console.log(value);
        this.handleChangeExtendedPrice()
    }

    handleChangeTaxable1 = async (event: any) => {
        const value = event.target.value;
        await this.setState({ Taxable1: value })
        console.log(value);
        this.handleChangeExtendedPrice()
    }

    handleChangeExtendedPrice() {
        if (this.state.Taxable1 === "Yes") {
            this.setState({ 
                ExtendedPrice: (this.state.Quantity * this.state.UnitPrice) + ((this.state.Quantity * this.state.UnitPrice) * .08),
                TaxAmount1: (this.state.Quantity * this.state.UnitPrice) * .08
            }); 
        } else {
            this.setState({ 
                ExtendedPrice: this.state.Quantity * this.state.UnitPrice,
            }); 
        }
        console.log(this.state.ExtendedPrice);
        this.handleChangeEstimatedTotal();      
    }

    handleChangeEstimatedSalesTax = async () => {
        await this.setState({ 
            EstimatedSalesTax: this.state.TaxAmount1 + this.state.TaxAmount2,
        }); 
        console.log(this.state.EstimatedSalesTax);      
    }   

    handleChangeEstimatedTotal = async () => {
        await this.setState({ 
            EstimatedTotal: this.state.ExtendedPrice + this.state.ExtendedPrice2 + this.state.EstimatedSalesTax,
        }); 
        console.log(this.state.EstimatedTotal);
        this.handleChangeEstimatedSalesTax();
    }


    public render(): React.ReactElement<{}> {

        return (
            <div>
                <form onSubmit={this._onNewRequest}>

                    <div>
                        <div>
                            <label>
                                Quantity <br /> (Units)
                            </label>
                            <input
                                value={this.state.Quantity}
                                onChange={this.handleChangeQuantity}
                                type="number"
                                maxLength={9}
                                pattern='[0-9]{0,5}'
                            />
                        </div>
                        <div>
                            <label>
                                Estimated<br /> Unit Price
                            </label>
                            <input
                                value={this.state.UnitPrice}
                                onChange={this.handleChangeUnitPrice}
                                type="number"
                                pattern='[0-9]{0,5}'
                                prefix={'$'}                                            
                            />
                        </div>
                        <div>
                            <label>
                                Estimated<br /> Extended Price
                            </label>
                            <input
                                value={this.state.ExtendedPrice}
                                //onChange={(e) => this.handleChangeUnitPrice(e)}
                                type="number"
                                disabled
                            />
                        </div>
                        <div>
                            <label>
                                Taxable?
                            </label>
                            <select name="Taxable1" value={this.state.Taxable1} onChange={this.handleChangeTaxable1}> 
                                <option value="No">No</option>
                                <option value="Yes">Yes</option>                            
                            </select>
                        </div>                                                                      
                    </div>


                    <div>
                        <div>
                            <label>
                                Estimated Sales Tax
                            </label>
                            <input
                                value={this.state.EstimatedSalesTax}
                                type="number"
                                disabled
                            />
                        </div>
                        <div>
                            <label>
                                Estimated Total
                            </label>
                            <input
                                value={this.state.EstimatedTotal}
                                type="number"
                                disabled
                            />
                        </div>                                                                              
                    </div>                                                                                              

                </form>

        );
    }
}

【问题讨论】:

  • 您不应等待setState。如果您想在更新后做某事,可以使用回调样式this.setState({ Quantity: value }, this.handleChangeExtendedPrice);
  • @topched 当我删除等待时。自为征税。然后它在加载时执行。所以在数量和单价之前可以填写。它会说我的税是0.8。难以解释。我也不是最擅长反应的。
  • 很难说发生了什么。删除所有 async 和 await 关键字,然后在状态更新后使用回调样式运行操作。请注意,当您执行 setState() 和 console.log(this.state) 时,不能保证此时 this.state 会更新。状态更新不是同步的,它们是由 react 安排的,可以批量处理

标签: javascript reactjs typescript async-await react-redux


【解决方案1】:

这将解决您的问题:

export class Screen1 extends React.Component<{}, {
    Quantity: number, 
    UnitPrice: number,
    ExtendedPrice: number,
    Taxable1: string,
    TaxAmount1: number,
    Quantity2: number, 
    UnitPrice2: number,
    ExtendedPrice2: number,
    Taxable2: string,
    TaxAmount2: number,
    EstimatedTotal: number;
    EstimatedSalesTax: number;
}> {

    constructor(props) {
        super(props);
        this.state = {
            Quantity: null,
            UnitPrice: null,
            ExtendedPrice: null,
            Taxable1: '',
            TaxAmount1: null,
            Quantity2: null,
            UnitPrice2: null,
            ExtendedPrice2: null,
            Taxable2: '',
            TaxAmount2: null,                   
            EstimatedTotal: null,
            EstimatedSalesTax: 0,                       
        };

        this.handleChangeQuantity = this.handleChangeQuantity.bind(this);
        this.handleChangeUnitPrice = this.handleChangeUnitPrice.bind(this);
        this.handleChangeExtendedPrice = this.handleChangeExtendedPrice.bind(this);
        this.handleChangeTaxable1 = this.handleChangeTaxable1.bind(this);

        this.handleChangeEstimatedTotal = this.handleChangeEstimatedTotal.bind(this);
        this.handleChangeEstimatedSalesTax = this.handleChangeEstimatedSalesTax.bind(this);

    }


    handleChangeQuantity = async (event: any) => {
        const value = parseInt(event.target.value)
        await this.setState({ Quantity: value })
        console.log(value);
        this.handleChangeExtendedPrice()
      }

    handleChangeUnitPrice = async (event: any) => {
        const value = parseInt(event.target.value)
        await this.setState({ UnitPrice: value })
        console.log(value);
        this.handleChangeExtendedPrice()
    }

    handleChangeTaxable1 = async (event: any) => {
        const value = event.target.value;
        await this.setState({ Taxable1: value })
        console.log(value);
        this.handleChangeExtendedPrice()
    }

    handleChangeExtendedPrice() {
        if (this.state.Taxable1 === "Yes") {
            this.setState({ 
                ExtendedPrice: (this.state.Quantity * this.state.UnitPrice),
                TaxAmount1: (this.state.Quantity * this.state.UnitPrice) * .08
            }); 
        } else {
            //***You must reset TaxAmount1...
            this.setState({ 
                ExtendedPrice: this.state.Quantity * this.state.UnitPrice,
                TaxAmount1: 0
            }); 
        }
        console.log(this.state.ExtendedPrice);
        this.handleChangeEstimatedTotal();      
    }

    handleChangeEstimatedSalesTax = async () => {
        await this.setState({ 
            EstimatedSalesTax: this.state.TaxAmount1 + this.state.TaxAmount2,
        }); 
        console.log(this.state.EstimatedSalesTax);      
    }   

    handleChangeEstimatedTotal = async () => {
        //***first calculate tax then calculate the total...
        await this.handleChangeEstimatedSalesTax();

        await this.setState({ 
            EstimatedTotal: this.state.ExtendedPrice + this.state.ExtendedPrice2 + this.state.EstimatedSalesTax,
        }); 

        console.log(this.state.EstimatedTotal);

    }


    public render(): React.ReactElement<{}> {

        return (
            <div>
                <form onSubmit={this._onNewRequest}>

                    <div>
                        <div>
                            <label>
                                Quantity <br /> (Units)
                            </label>
                            <input
                                value={this.state.Quantity}
                                onChange={this.handleChangeQuantity}
                                type="number"
                                maxLength={9}
                                pattern='[0-9]{0,5}'
                            />
                        </div>
                        <div>
                            <label>
                                Estimated<br /> Unit Price
                            </label>
                            <input
                                value={this.state.UnitPrice}
                                onChange={this.handleChangeUnitPrice}
                                type="number"
                                pattern='[0-9]{0,5}'
                                prefix={'$'}                                            
                            />
                        </div>
                        <div>
                            <label>
                                Estimated<br /> Extended Price
                            </label>
                            <input
                                value={this.state.ExtendedPrice}
                                //onChange={(e) => this.handleChangeUnitPrice(e)}
                                type="number"
                                disabled
                            />
                        </div>
                        <div>
                            <label>
                                Taxable?
                            </label>
                            <select name="Taxable1" value={this.state.Taxable1} onChange={this.handleChangeTaxable1}> 
                                <option value="No">No</option>
                                <option value="Yes">Yes</option>                            
                            </select>
                        </div>                                                                      
                    </div>


                    <div>
                        <div>
                            <label>
                                Estimated Sales Tax
                            </label>
                            <input
                                value={this.state.EstimatedSalesTax}
                                type="number"
                                disabled
                            />
                        </div>
                        <div>
                            <label>
                                Estimated Total
                            </label>
                            <input
                                value={this.state.EstimatedTotal}
                                type="number"
                                disabled
                            />
                        </div>                                                                              
                    </div>                                                                                              

                </form>
                </div>

        );
    }
}


render(<App />, document.getElementById('root'));

我所做的改变:

1.) 在handleChangeExtendedPrice() 中,我更改了 else 条件,因为 TaxAmount1 必须重置为 0,这可能是更改未反映的原因...

handleChangeExtendedPrice() {
        if (this.state.Taxable1 === "Yes") {
            this.setState({ 
                ExtendedPrice: (this.state.Quantity * this.state.UnitPrice),
                TaxAmount1: (this.state.Quantity * this.state.UnitPrice) * .08
            }); 
        } else {
            //***You must reset TaxAmount1...
            this.setState({ 
                ExtendedPrice: this.state.Quantity * this.state.UnitPrice,
                TaxAmount1: 0
            }); 
        }
        console.log(this.state.ExtendedPrice);
        this.handleChangeEstimatedTotal();      
    }

2.) 我已将 handleChangeEstimatedTotal 更改为调用 this.handleChangeEstimateSalesTax() ,因为我们必须先计算税值然后继续!

handleChangeEstimatedTotal = async () => {
        //***first calculate tax then calculate the total...
        await this.handleChangeEstimatedSalesTax();

        await this.setState({ 
            EstimatedTotal: this.state.ExtendedPrice + this.state.ExtendedPrice2 + this.state.EstimatedSalesTax,
        }); 

        console.log(this.state.EstimatedTotal);

    }

这样做有望解决您的问题

【讨论】:

  • 谢谢!!!这就像一个魅力。我将更多地研究解决方案以更好地掌握。这绝对是有帮助的!
  • 谢谢,如果您需要任何帮助,请询问。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-01
  • 2016-10-14
  • 1970-01-01
  • 2021-11-13
  • 2021-12-03
  • 1970-01-01
  • 2022-07-11
相关资源
最近更新 更多