我有一个反应表单组件 - 它有一个方法,在已更新的表单上输入_handleInputChange并将更改添加到状态。 我正在尝试添加一个_calculatePrice ,顾名思义,它计算预订价格。 我试图让它显示给用户,这样当输入字段发生变化时,价格变化就会反映出来。
我正在努力弄清楚如何正确执行 - 我想这是缺乏对生命周期反应的知识,我已经阅读了文档并在堆栈上搜索了几个问题,但是,答案似乎在逃避我。 随着_calculatePrice方法更新一个状态值,然后再次调用自己,包含的示例会卡在循环中。
任何帮助将非常感激。
谢谢
Form.jsx
import React, { Component } from 'react'; import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; class AddBooking extends Component { constructor(props) { super(props); this.state = { pitch: this.props.pitch, firstName: null, lastName: null, email: null, arrivalDate: this.props.dayQuery, departureDate: this.props.dayQuery, noDays: 1, pitchType: "Standard", adults: 0, children: 0, infants: 0, hookUp: 0, dogs: 0, extraInfo: null, price: 0, deposit: 0, paid: 0, subTotal: 0, total: 0, } this._handleDisplay = this._handleDisplay.bind(this); this._getRefs = this._getRefs.bind(this); this._handleInputChange = this._handleInputChange.bind(this); this._calculatePrice = this._calculatePrice.bind(this); } componentDidUpdate() { this._calculatePrice(this.state); } _getRefs(e) { var tempBooking = { pitch: parseInt(this.state.pitch), firstName: this.state.firstName, lastName: this.state.lastName, email: this.state.email, arrivalDate: this.state.arrivalDate, departureDate: this.state.departureDate, pitchType: this.state.pitchType, adults: parseInt(this.state.adults), children: this.state.children, infants: this.state.infants, hookUp: this.state.hookUp, dogs: this.state.dogs, extraInfo: this.state.extraInfo, price: this.state.price, deposit: this.state.deposit, paid: this.state.paid } this.props.addBooking(tempBooking); e.preventDefault(); this._handleDisplay(); } _calculatePrice(data) { var price = this.props.bookingPrice.in_season; var a = (data.adults * price.adults); var c = (data.children * price.children); var i = (data.infants * price.infants); var h = (data.hookUp * price.hookUp); var d = (data.dogs * price.dogs); var days = data.noDays; var subTotal = a + c + i + h + d; var total = subTotal * days; this.setState({ subTotal: subTotal, total: total }); } _handleDisplay() { this.props.addDisplay(); } _handleInputChange(event) { const target = event.target; const value = target.type === 'checkbox' ? target.checked : target.value; const name = target.name; var partialState = {}; partialState[name] = value; this.setState(partialState); } render(){ var price = this.props.bookingPrice.in_season; return ( <Modal isOpen={this.props.formVisibility} toggle={this._handleDisplay}> <ModalHeader toggle={this._handleDisplay}>Add Booking</ModalHeader> <ModalBody> <div className="modal-body"> <div className="row"> <div className="col-7"> <form id="add-booking-form"> <i className="fa fa-address-card float-left mr-2 mt-1" aria-hidden="true"></i> <h5>Personal</h5> <div className="form-group row mt-3"> <div className="form-label-group col-6"> <input onChange={this._handleInputChange} id="firstName" className="form-control" ref="firstName" name="firstName" type="text" placeholder="First Name"/> <label htmlFor="firstName" className="mx-3">First Name</label> </div> <div className="form-label-group col-6"> <input onChange={this._handleInputChange} id="lastName" className="form-control" ref="lastName" name="lastName" type="text" placeholder="Last Name"/> <label htmlFor="lastName" className="mx-3">Last Name</label> </div> </div> <div className="form-label-group"> <input onChange={this._handleInputChange} id="email" className="form-control" ref="email" name="email" type="email" placeholder="Email Address"/> <label htmlFor="email">Email Address</label> </div> <hr className="mb-4 mt-4"></hr> <i className="fa fa-calendar float-left mr-2 mt-1" aria-hidden="true"></i> <h5>Pitch</h5> <div className="form-group row mt-3"> <div className="form-label-group col-6"> <input defaultValue={this.props.pitch} onChange={this._handleInputChange} id="pitch" className="form-control" ref="pitch" name="pitch" type="number" placeholder="Pitch"/> <label htmlFor="pitch" className="mx-3">Pitch</label> </div> <div className="form-label-group col-6"> <input onChange={this._handleInputChange} id="pitchType" className="form-control" ref="pitchType" name="pitchType" type="text" placeholder="Pitch Type"/> <label htmlFor="pitchType" className="mx-3">Pitch Type</label> </div> </div> <div className="form-group row"> <div className="form-label-group col-6"> <input defaultValue={this.props.dayQuery} onChange={this._handleInputChange} id="arrivalDate" className="form-control" ref="arrivalDate" name="arrivalDate" type="date" placeholder="Arrival"/> <label htmlFor="arrivalDate" className="mx-3">Arrival</label> </div> <div className="form-label-group col-6"> <input defaultValue={this.props.dayQuery} onChange={this._handleInputChange} id="departureDate" className="form-control" ref="departureDate" name="departureDate" type="date" placeholder="Departure"/> <label htmlFor="departureDate" className="mx-3">Departure</label> </div> </div> <hr className="mb-4"></hr> <i className="fa fa-users float-left mr-2 mt-1" aria-hidden="true"></i> <h5>Group Details</h5> <div className="form-group row mt-3"> <div className="form-label-group col-4"> <input onChange={this._handleInputChange} id="adults" className="form-control" ref="adults" name="adults" type="number" placeholder="Adults"/> <label htmlFor="adults" className="mx-3">Adults</label> <small id="emailHelp" className="form-text text-muted">18+</small> </div> <div className="form-label-group col-4"> <input onChange={this._handleInputChange} id="children" className="form-control" ref="children" name="children" type="number" placeholder="Children"/> <label htmlFor="children" className="mx-3">Children</label> <small id="emailHelp" className="form-text text-muted">12-17</small> </div> <div className="form-label-group col-4"> <input onChange={this._handleInputChange} id="infants" className="form-control" ref="infants" name="infants" type="number" placeholder="Infants"/> <label htmlFor="infants" className="mx-3">Infants</label> <small id="emailHelp" className="form-text text-muted">4+</small> </div> </div> <div className="form-group row mt-3"> <div className="form-label-group col-6"> <input onChange={this._handleInputChange} id="hookUp" className="form-control" ref="hookUp" name="hookUp" type="number" placeholder="Hook Up"/> <label htmlFor="hookUp" className="mx-3">Hook Up</label> </div> <div className="form-label-group col-6"> <input onChange={this._handleInputChange} id="dogs" className="form-control" ref="dogs" name="dogs" type="number" placeholder="Dogs"/> <label htmlFor="dogs" className="mx-3">Dogs</label> </div> </div> <div className="form-group row mt-3"> <div className="form-group col-12"> <textarea className="form-control" id="exampleFormControlTextarea1" placeholder="Extra Info" rows="3"></textarea> </div> </div> <div className="form-group row"> <label className="col-2 col-form-label">Price</label> <div className="col-10"> <input onChange={this._handleInputChange} className="form-control" ref="price" name="price" type="number"/> </div> </div> <div className="form-group row"> <label className="col-2 col-form-label">Deposit</label> <div className="col-10"> <input onChange={this._handleInputChange} className="form-control" ref="deposit" name="deposit" type="number"/> </div> </div> <div className="form-group row"> <label className="col-2 col-form-label">Paid</label> <div className="col-10"> <input onChange={this._handleInputChange} className="form-control" ref="paid" name="paid" type="number"/> </div> </div> </form> </div> <div className="col-5"> <i className="fa fa-calculator float-left mr-2 mt-1" aria-hidden="true"></i> <h4>Booking Price</h4> <small id="passwordHelpBlock" className="form-text text-muted"> Summer Tariff & Forest Pitch </small> <ul className="list-group list-group-flush mt-3"> <li className={"list-group-item d-flex justify-content-between align-items-center " + (this.state.adults ? 'show' : 'hidden')}> Adults x{this.state.adults} <span className="pull-right">£{price.adults * this.state.adults}</span> </li> <li className={"list-group-item d-flex justify-content-between align-items-center " + (this.state.children ? 'show' : 'hidden')}> Children x3 <span className="pull-right">£{price.children * this.state.children}</span> </li> <li className={"list-group-item d-flex justify-content-between align-items-center " + (this.state.infants ? 'show' : 'hidden')}> Infants x2 <span className="pull-right">£{price.infants * this.state.infants}</span> </li> <li className="list-group-item d-flex justify-content-between align-items-center"> Subtotal (cost per night) <span className="pull-right">£0</span> </li> <li className="list-group-item d-flex justify-content-between align-items-center font-weight-bold"> Total <span className="pull-right">£0</span> </li> </ul> </div> </div> </div> </ModalBody> <ModalFooter> <Button color="danger" data-dismiss="modal" onClick={this._handleDisplay}>Close</Button> <Button color="success" onClick={this._getRefs}>Save</Button> </ModalFooter> </Modal> ) } } export default AddBooking;I've got a react form component - it's got a method that _handleInputChange on the updated form input and adds the change to state. I'm trying to add a _calculatePrice, which as the name suggests, calculates the booking price. I'm trying to get it to display to the user so that when the input field alters, the price change is reflected.
I'm struggling to figure out how to execute this correctly - I imagine it's a lack of knowledge of react lifecycles, I have read the docs and search for a few questions on stack, however, the answer seems to be evading me. The example included gets stuck in a loop as the _calculatePrice method updates a state value which then calls itself again.
Any help would be much appreciated.
Thanks
Form.jsx
import React, { Component } from 'react'; import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; class AddBooking extends Component { constructor(props) { super(props); this.state = { pitch: this.props.pitch, firstName: null, lastName: null, email: null, arrivalDate: this.props.dayQuery, departureDate: this.props.dayQuery, noDays: 1, pitchType: "Standard", adults: 0, children: 0, infants: 0, hookUp: 0, dogs: 0, extraInfo: null, price: 0, deposit: 0, paid: 0, subTotal: 0, total: 0, } this._handleDisplay = this._handleDisplay.bind(this); this._getRefs = this._getRefs.bind(this); this._handleInputChange = this._handleInputChange.bind(this); this._calculatePrice = this._calculatePrice.bind(this); } componentDidUpdate() { this._calculatePrice(this.state); } _getRefs(e) { var tempBooking = { pitch: parseInt(this.state.pitch), firstName: this.state.firstName, lastName: this.state.lastName, email: this.state.email, arrivalDate: this.state.arrivalDate, departureDate: this.state.departureDate, pitchType: this.state.pitchType, adults: parseInt(this.state.adults), children: this.state.children, infants: this.state.infants, hookUp: this.state.hookUp, dogs: this.state.dogs, extraInfo: this.state.extraInfo, price: this.state.price, deposit: this.state.deposit, paid: this.state.paid } this.props.addBooking(tempBooking); e.preventDefault(); this._handleDisplay(); } _calculatePrice(data) { var price = this.props.bookingPrice.in_season; var a = (data.adults * price.adults); var c = (data.children * price.children); var i = (data.infants * price.infants); var h = (data.hookUp * price.hookUp); var d = (data.dogs * price.dogs); var days = data.noDays; var subTotal = a + c + i + h + d; var total = subTotal * days; this.setState({ subTotal: subTotal, total: total }); } _handleDisplay() { this.props.addDisplay(); } _handleInputChange(event) { const target = event.target; const value = target.type === 'checkbox' ? target.checked : target.value; const name = target.name; var partialState = {}; partialState[name] = value; this.setState(partialState); } render(){ var price = this.props.bookingPrice.in_season; return ( <Modal isOpen={this.props.formVisibility} toggle={this._handleDisplay}> <ModalHeader toggle={this._handleDisplay}>Add Booking</ModalHeader> <ModalBody> <div className="modal-body"> <div className="row"> <div className="col-7"> <form id="add-booking-form"> <i className="fa fa-address-card float-left mr-2 mt-1" aria-hidden="true"></i> <h5>Personal</h5> <div className="form-group row mt-3"> <div className="form-label-group col-6"> <input onChange={this._handleInputChange} id="firstName" className="form-control" ref="firstName" name="firstName" type="text" placeholder="First Name"/> <label htmlFor="firstName" className="mx-3">First Name</label> </div> <div className="form-label-group col-6"> <input onChange={this._handleInputChange} id="lastName" className="form-control" ref="lastName" name="lastName" type="text" placeholder="Last Name"/> <label htmlFor="lastName" className="mx-3">Last Name</label> </div> </div> <div className="form-label-group"> <input onChange={this._handleInputChange} id="email" className="form-control" ref="email" name="email" type="email" placeholder="Email Address"/> <label htmlFor="email">Email Address</label> </div> <hr className="mb-4 mt-4"></hr> <i className="fa fa-calendar float-left mr-2 mt-1" aria-hidden="true"></i> <h5>Pitch</h5> <div className="form-group row mt-3"> <div className="form-label-group col-6"> <input defaultValue={this.props.pitch} onChange={this._handleInputChange} id="pitch" className="form-control" ref="pitch" name="pitch" type="number" placeholder="Pitch"/> <label htmlFor="pitch" className="mx-3">Pitch</label> </div> <div className="form-label-group col-6"> <input onChange={this._handleInputChange} id="pitchType" className="form-control" ref="pitchType" name="pitchType" type="text" placeholder="Pitch Type"/> <label htmlFor="pitchType" className="mx-3">Pitch Type</label> </div> </div> <div className="form-group row"> <div className="form-label-group col-6"> <input defaultValue={this.props.dayQuery} onChange={this._handleInputChange} id="arrivalDate" className="form-control" ref="arrivalDate" name="arrivalDate" type="date" placeholder="Arrival"/> <label htmlFor="arrivalDate" className="mx-3">Arrival</label> </div> <div className="form-label-group col-6"> <input defaultValue={this.props.dayQuery} onChange={this._handleInputChange} id="departureDate" className="form-control" ref="departureDate" name="departureDate" type="date" placeholder="Departure"/> <label htmlFor="departureDate" className="mx-3">Departure</label> </div> </div> <hr className="mb-4"></hr> <i className="fa fa-users float-left mr-2 mt-1" aria-hidden="true"></i> <h5>Group Details</h5> <div className="form-group row mt-3"> <div className="form-label-group col-4"> <input onChange={this._handleInputChange} id="adults" className="form-control" ref="adults" name="adults" type="number" placeholder="Adults"/> <label htmlFor="adults" className="mx-3">Adults</label> <small id="emailHelp" className="form-text text-muted">18+</small> </div> <div className="form-label-group col-4"> <input onChange={this._handleInputChange} id="children" className="form-control" ref="children" name="children" type="number" placeholder="Children"/> <label htmlFor="children" className="mx-3">Children</label> <small id="emailHelp" className="form-text text-muted">12-17</small> </div> <div className="form-label-group col-4"> <input onChange={this._handleInputChange} id="infants" className="form-control" ref="infants" name="infants" type="number" placeholder="Infants"/> <label htmlFor="infants" className="mx-3">Infants</label> <small id="emailHelp" className="form-text text-muted">4+</small> </div> </div> <div className="form-group row mt-3"> <div className="form-label-group col-6"> <input onChange={this._handleInputChange} id="hookUp" className="form-control" ref="hookUp" name="hookUp" type="number" placeholder="Hook Up"/> <label htmlFor="hookUp" className="mx-3">Hook Up</label> </div> <div className="form-label-group col-6"> <input onChange={this._handleInputChange} id="dogs" className="form-control" ref="dogs" name="dogs" type="number" placeholder="Dogs"/> <label htmlFor="dogs" className="mx-3">Dogs</label> </div> </div> <div className="form-group row mt-3"> <div className="form-group col-12"> <textarea className="form-control" id="exampleFormControlTextarea1" placeholder="Extra Info" rows="3"></textarea> </div> </div> <div className="form-group row"> <label className="col-2 col-form-label">Price</label> <div className="col-10"> <input onChange={this._handleInputChange} className="form-control" ref="price" name="price" type="number"/> </div> </div> <div className="form-group row"> <label className="col-2 col-form-label">Deposit</label> <div className="col-10"> <input onChange={this._handleInputChange} className="form-control" ref="deposit" name="deposit" type="number"/> </div> </div> <div className="form-group row"> <label className="col-2 col-form-label">Paid</label> <div className="col-10"> <input onChange={this._handleInputChange} className="form-control" ref="paid" name="paid" type="number"/> </div> </div> </form> </div> <div className="col-5"> <i className="fa fa-calculator float-left mr-2 mt-1" aria-hidden="true"></i> <h4>Booking Price</h4> <small id="passwordHelpBlock" className="form-text text-muted"> Summer Tariff & Forest Pitch </small> <ul className="list-group list-group-flush mt-3"> <li className={"list-group-item d-flex justify-content-between align-items-center " + (this.state.adults ? 'show' : 'hidden')}> Adults x{this.state.adults} <span className="pull-right">£{price.adults * this.state.adults}</span> </li> <li className={"list-group-item d-flex justify-content-between align-items-center " + (this.state.children ? 'show' : 'hidden')}> Children x3 <span className="pull-right">£{price.children * this.state.children}</span> </li> <li className={"list-group-item d-flex justify-content-between align-items-center " + (this.state.infants ? 'show' : 'hidden')}> Infants x2 <span className="pull-right">£{price.infants * this.state.infants}</span> </li> <li className="list-group-item d-flex justify-content-between align-items-center"> Subtotal (cost per night) <span className="pull-right">£0</span> </li> <li className="list-group-item d-flex justify-content-between align-items-center font-weight-bold"> Total <span className="pull-right">£0</span> </li> </ul> </div> </div> </div> </ModalBody> <ModalFooter> <Button color="danger" data-dismiss="modal" onClick={this._handleDisplay}>Close</Button> <Button color="success" onClick={this._getRefs}>Save</Button> </ModalFooter> </Modal> ) } } export default AddBooking;最满意答案
尽量不要在您的州中包含重复信息。
例如,如果您的状态包含firstName和lastName ,则不需要fullName另一个状态。
尝试从你的状态中删除subTotal和total 。 相反,请在render方法内计算它。 这样,您可以避免导致setState调用的无限循环。
我创建了这个CodeSandbox ,它显示了一个简单的例子。
Try not to include duplicate information in your state.
For example, if your state contained firstName and lastName, you wouldn't need another state for fullName.
Try removing subTotal and total from your state. Instead, calculate it inside of your render method. This way, you avoid causing an infinite loop with your setState calls.
I created this CodeSandbox that shows a simple example of this.
更多推荐
发布评论