我正在尝试使用表单输入元素,由于我们使用了 jQuery UI DatePicker,这些元素是不受控制的和 jQuery maskMoney ,一旦用户键入对该字段无效的内容,就会在它们下面呈现错误,并禁用任何错误上的按钮。出于某种原因,none of that is working right .
主要成分
类似于下面的内容:
class MainComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
payrates: [
new PayRate(new Date(2019, 2, 1), 0.00),
],
errors : {
rate: '',
date: ''
},
currentPayRate : new PayRate() // has Rate and EffectiveDate fields
}
// binding done here
this.appendValue = this.appendValue.bind(this)
this.updateCurrentPayRate = this.updateCurrentPayRate.bind(this)
this.updateCurrentPayRateDate = this.updateCurrentPayRateDate.bind(this)
this.updateCurrentPayRateAmount = this.updateCurrentPayRateAmount.bind(this)
this.validate = this.validate.bind(this)
}
/**
* @param { PayRate } newPayRate
**/
updateCurrentPayRate(newPayRate) {
this.setState({
...this.state,
currentPayRate : newPayRate
})
}
updateCurrentPayRateDate(dateString) {
const newPayRate = Object.assign(new PayRate(), this.state.currentPayRate, { EffectiveDate : new Date(dateString) } )
this.validate(newPayRate)
this.updateCurrentPayRate(newPayRate)
}
updateCurrentPayRateAmount(amount) {
const newPayRate = Object.assign(new PayRate(), this.state.currentPayRate, { Rate : Number(amount) } )
this.validate(newPayRate)
this.updateCurrentPayRate(newPayRate)
}
/**
* @param { PayRate } value
**/
appendValue(value) {
console.log("trying to append value: ", value)
if (this.validate(value)) {
this.setState({...this.state,
payrates : this.state.payrates.concat(this.state.currentPayRate)})
}
}
/**
* @param { PayRate } value
**/
validate(value) {
// extract rate,date from value
const rate = value.Rate,
date = value.EffectiveDate
console.log("value == ", value)
let errors = {}
// rate better resolve to something
if (!rate) {
errors.rate = "Enter a valid pay rate amount"
}
// date better be valid
if ((!date) || (!date.toLocaleDateString)) {
errors.date = "Enter a date"
}
else if (date.toLocaleDateString("en-US") === "Invalid Date") {
errors.date = "Enter a valid pay rate date"
}
console.log(errors)
// update the state with the errors
this.setState({
...this.state,
errors : errors
})
const errorsToArray = Object.values(errors).filter((error) => error)
return !errorsToArray.length;
}
render() {
return <div>
<DateList dates={this.state.payrates}/>
<NewPayRateRow
value={this.state.currentPayRate}
errors={this.state.errors}
onChange={this.updateCurrentPayRate}
onPayRateAmountChange={this.updateCurrentPayRateAmount}
onPayRateDateChange={this.updateCurrentPayRateDate}
onAdd={this.appendValue}
/>
</div>
}
}
“表单”组件
具有以下实现:
class NewPayRateRow extends React.Component {
constructor(props) {
super(props)
}
render() {
console.log(Object.values(this.props.errors).filter((error) => error))
return <span class="form-inline">
<RateField
errors={this.props.errors.rate}
onKeyUp={(e) => {
// extract the value
const value = e.target.value
this.props.onPayRateAmountChange(value)
}}
/>
<DateInput
errors={this.props.errors.date}
onChange={this.props.onPayRateDateChange}
/>
<button onClick={(e) => {
this.props.onAdd(this.props.value)
}}
disabled={Object.values(this.props.errors).filter((error) => error).length}>Add New Pay Rate</button>
</span>
}
}
不受控制的输入组件
问题肯定发生的地方:
class DateInput extends React.Component {
constructor(props) {
super(props);
// do bindings
this.handleChange = this.handleChange.bind(this);
}
componentDidMount() {
$('#datepicker').datepicker({
changeMonth: true,
changeYear: true,
showButtonPanel: true,
yearRange: "-116:+34",
dateFormat: 'mm/dd/yy',
// telling jQuery UI to pass its event to React
onSelect : this.handleChange
});
}
componentWillUnmount() {
$('#datepicker').datepicker('destroy')
}
// handles a change to the input field
handleChange(value) {
this.props.onChange(value)
}
render() {
const fieldIsInvalid = this.props.errors || ''
return <div class="col-md-2">
<input
id="datepicker"
className={"datepicker form-control " + fieldIsInvalid }
placeholder="mm/dd/yyyy"
onChange={(e) => this.props.onChange(e.target.value) }>
</input>
<div>
{this.props.errors}
</div>
</div>
}
}
出于某种原因,即使我通过日期选择器小部件选择值,错误
也不会改变:
但是,当我注释掉所有 validate
调用时,它添加字段没问题。
我对传递给 validate
的 value
进行了一些穴居人调试,以确保传递的是真实数据。
为什么 this.state.error
没有通过组件正确更新?!
更新:最初我只更新了工资率,错误呈现正确,通过代码,我发现 this.setState
是实际上设置状态。但是,当我去触发输入货币字段的更改时,this.setState
被击中,errors
对象为空(这是正确的),但不知何故, this.setState
实际上并没有更新状态。
最佳答案
我解决了这个问题!
我做了什么
不是在全局 state
中持久化 errors
,也不是将 validate
传递给方法来设置全局状态,我将其维护为在主要组件类之外定义的函数,如下所示:
/**
* Validates a PayRate
* @param { PayRate } value
* @returns { Object } any errors
**/
function validate(value = {}) {
// extract rate,date from value
const rate = value.Rate,
date = value.EffectiveDate
let errors = {}
// rate better resolve to something
if (!rate) {
errors.rate = "Enter a valid pay rate amount"
}
// date better be valid
if ((!date) || (!date.toLocaleDateString)) {
errors.date = "Enter a date"
}
else if (date.toLocaleDateString("en-US") === "Invalid Date") {
errors.date = "Enter a valid pay rate date"
}
return errors
}
注意更简单的实现。然后,我不再需要在 updateCurrentPayRate...
方法上调用 validate
。
相反,我在 NewPayRateRow.render
上调用它(我现在可以这样做,因为它根本不接触状态,避免了任何不变违规),将结果保存到本地常量变量,称为 errors
,并使用它代替 this.props.errors
。不过,说实话,我可能可以将 validate
放回 this.props
中以实现抽象层/可扩展性。
此外,我采纳了 Pagoaga 的建议并使用 className
而不是 class
(我还没有把它当作肌肉内存)。
关于javascript - 在子组件上 react 过时的错误日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55053503/