【发布时间】:2017-07-17 07:52:02
【问题描述】:
我有一个表单,其中包含年、月和日的选择下拉菜单。
<select onChange={(event) => this.mergeDate('day', event.target.value)}>
<option value="1">1</option>
...
</select>
<select onChange={(event) => this.mergeDate('month', event.target.value)}>
<option value="1">January</option>
...
</select>
<select onChange={(event) => this.mergeDate('year', event.target.value)}>
<option value="1977">1e977</option>
...
</select>
我需要从这些值中创建日期并将它们存储在状态的birthday 字段中。为此,我创建了三个附加属性,分别为 date_day、date_mth 和 date_year。
this.state = {
name: '',
email: '',
birthday: '',
country: '',
date_day: '',
date_mth: '',
date_year: ''
}
在选择下拉菜单更改时,我创建了一个使用Date() 函数合并值的函数,如下所示:
mergeDate(type, value)
{
if (type === 'year') { this.setState({ date_year: value }) }
if (type === 'month') { this.setState({ date_mth: value }) }
if (type === 'day') { this.setState({ date_day: value }) }
console.log('merging date now '); // --> Works!
let newDate = new Date(this.state.date_year, this.state.date_mth, this.state.date_day);
console.log(newDate); // --> successful, but shows date value of last onChange event
this.setState({ birthday: newDate });
console.log(this.state); // --> {...., birthday: '', ....}
}
在这个函数中,第二个console.log 显示了上次onChange 事件设置的日期。最后一个 console.log 在birthday 中记录空值。我猜这个问题是因为setState 的asynchronous behavior 我还不明白。谁能给我解释一下问题的原因和解决方法?
===========
更新
根据 Asad 的说法,setState 是 asynchronous,设置状态完成后要执行的任何操作都应作为参数传递给 setState 函数。我试过了:
postUpdate()
{
let newDate = new Date(this.state.date_year, this.state.date_mth, this.state.date_day);
this.setState({ birthday : newDate });
}
mergeDate(type, value)
{
if (type === 'year') { this.setState({ date_year:value }, this.postUpdate(newDate))}
if (type === 'month') { this.setState({ date_mth: value }, this.postUpdate(newDate))}
if (type === 'day') { this.setState({ date_day: value }, this.postUpdate(newDate))}
}
这仍然给我相同的输出 - 显示最后一次 onChange 事件的日期值。我错过了什么?
========
解决方案
解决方法是不要单独传递函数,而是作为函数传递。
mergeDate(type, value)
{
if (type === 'year') { this.setState({ date_year:value }, () => this.postUpdate())}
if (type === 'month') { this.setState({ date_mth: value }, () => this.postUpdate())}
if (type === 'day') { this.setState({ date_day: value }, () => this.postUpdate())}
}
【问题讨论】:
-
你必须记住
setState是异步的。如果你想在它之后做一些事情,你应该传递一个回调作为第二个参数。 -
感谢您的回答,阿萨德。我应该发送什么样的回调?
-
您的更新问题是您实际上并没有传递函数,而是调用它。您只需要以与我在代码中相同的方式传递它,即
this.setState({ date_day: value }, postUpdate)。在您的情况下,您已将其设置为一种方法,因此您需要, this.postUpdate.bind(this)),但此时您已经在做的事情可能更具可读性。 -
这是很好的信息。再次感谢。
标签: reactjs