【问题标题】:Combining year, month and day to create date in ReactJS在 ReactJS 中结合年月日创建日期
【发布时间】: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_daydate_mthdate_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 中记录空值。我猜这个问题是因为setStateasynchronous behavior 我还不明白。谁能给我解释一下问题的原因和解决方法?

===========

更新

根据 Asad 的说法,setStateasynchronous,设置状态完成后要执行的任何操作都应作为参数传递给 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


【解决方案1】:

setState 是异步的,因为 React 经常批量更新状态以提高性能。这意味着您不能依赖setState 之后的语句中提供的新状态。如果您依赖更改的顺序,您应该传递一个回调,如下所示:

mergeDate(type, value)
{
        function postUpdate() {
            // All of the code from after your if statements
        }
        if (type === 'year')  { this.setState({ date_year: value }, postUpdate) }
        if (type === 'month') { this.setState({ date_mth: value  }, postUpdate) }
        if (type === 'day')   { this.setState({ date_day: value  }, postUpdate) }

}

不过,一般来说,您应该简单地预先进行所有计算,并在函数结束时调用一次setState,并对状态进行所有您想要的更改。

【讨论】:

  • 请花点时间看看我的问题,好吗?
  • 我想通了。这些信息很有帮助,谢谢。
  • @anonym 抱歉,当时处于离线状态,但很高兴您知道了。
猜你喜欢
  • 2020-01-24
  • 2015-10-10
  • 1970-01-01
  • 1970-01-01
  • 2013-05-06
  • 1970-01-01
  • 2017-10-24
  • 2011-04-26
  • 1970-01-01
相关资源
最近更新 更多